Compare commits
No commits in common. "6362f3bd0bcf85b61e5785e5787a6b7b98dfc5e1" and "bb35dd97a23c948d1a4f981a7b2bc85d308ce272" have entirely different histories.
6362f3bd0b
...
bb35dd97a2
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@ actix-web = { version = "4.3.0", default-features = false, features = [
|
|||
"compress-gzip",
|
||||
"compress-zstd",
|
||||
] }
|
||||
sqlx = { version = "0.8.2", default-features = false, features = [
|
||||
sqlx = { version = "0.7.1", default-features = false, features = [
|
||||
"runtime-tokio-rustls",
|
||||
"postgres",
|
||||
"time",
|
||||
|
@ -23,7 +23,7 @@ env_logger = { version = "0.11.3", default-features = false, features = [
|
|||
log = "0.4.17"
|
||||
actix-files = "0.6.2"
|
||||
tokio = { version = "1.25.0", features = ["rt-multi-thread", "macros", "sync"] }
|
||||
actix-multipart = "0.7.0"
|
||||
actix-multipart = "0.6.0"
|
||||
futures-util = "0.3.26"
|
||||
rand = "0.8.5"
|
||||
time = "0.3.17"
|
||||
|
@ -33,8 +33,10 @@ tree_magic_mini = { version = "3.0.3", features = ["with-gpl-data"] }
|
|||
tree_magic_db = "*"
|
||||
mime = "0.3.16"
|
||||
url = "2.3.1"
|
||||
actix-governor = "0.6.0"
|
||||
actix-governor = "0.5.0"
|
||||
governor = "0.6.3"
|
||||
lazy_static = "1.4.0"
|
||||
actix-web-lab = "0.20.2"
|
||||
|
||||
[profile.release]
|
||||
strip = "symbols"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM rust:alpine AS builder
|
||||
FROM rust:alpine as builder
|
||||
|
||||
WORKDIR /app
|
||||
RUN apk add musl-dev
|
||||
|
|
|
@ -22,7 +22,7 @@ use actix_web::{
|
|||
web::{self, Data},
|
||||
App, Error, HttpResponse, HttpServer,
|
||||
};
|
||||
use actix_web::middleware::from_fn;
|
||||
use actix_web_lab::middleware::from_fn;
|
||||
use env_logger::Env;
|
||||
use sqlx::postgres::PgPool;
|
||||
use std::env;
|
||||
|
@ -67,7 +67,7 @@ async fn main() -> std::io::Result<()> {
|
|||
let config = Data::new(config);
|
||||
|
||||
let governor_conf = GovernorConfigBuilder::default()
|
||||
.seconds_per_request(config.rate_limit_replenish_seconds)
|
||||
.per_second(config.rate_limit_replenish_seconds)
|
||||
.burst_size(config.rate_limit_burst)
|
||||
.key_extractor(ForwardedPeerIpKeyExtractor {
|
||||
proxied: config.proxied,
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use crate::{config, mime_relations};
|
||||
use actix_multipart::{Field, Multipart};
|
||||
use actix_web::{
|
||||
error,
|
||||
http::header::{ContentDisposition, DispositionParam},
|
||||
Error,
|
||||
};
|
||||
use actix_web::{error, http::header::DispositionParam, Error};
|
||||
use futures_util::{StreamExt, TryStreamExt};
|
||||
use mime::{Mime, APPLICATION_OCTET_STREAM, TEXT_PLAIN};
|
||||
use std::{cmp::min, io::ErrorKind, path::Path};
|
||||
|
@ -56,9 +52,7 @@ pub(crate) async fn parse_multipart_inner(
|
|||
let mut size = 0;
|
||||
|
||||
while let Ok(Some(mut field)) = payload.try_next().await {
|
||||
let name = get_field_name(&field)
|
||||
.ok_or(error::ParseError::Incomplete)?
|
||||
.to_owned();
|
||||
let name = get_field_name(&field)?.to_owned();
|
||||
match name.as_str() {
|
||||
"keep_for" => {
|
||||
keep_for_seconds = Some(parse_string(&name, &mut field).await?);
|
||||
|
@ -151,8 +145,11 @@ fn check_requirements(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_field_name(field: &Field) -> Option<&str> {
|
||||
field.content_disposition()?.get_name()
|
||||
fn get_field_name(field: &Field) -> Result<&str, error::Error> {
|
||||
Ok(field
|
||||
.content_disposition()
|
||||
.get_name()
|
||||
.ok_or(error::ParseError::Incomplete)?)
|
||||
}
|
||||
|
||||
async fn parse_string(
|
||||
|
@ -220,18 +217,15 @@ fn validate_max_size(written_bytes: u64, max_size: Option<u64>) -> Result<(), Er
|
|||
|
||||
fn get_file_metadata(field: &actix_multipart::Field) -> (Option<Mime>, Option<String>) {
|
||||
let mime = field.content_type().cloned();
|
||||
let filename = field.content_disposition().and_then(get_filename);
|
||||
(mime, filename)
|
||||
}
|
||||
|
||||
fn get_filename(content_disposition: &ContentDisposition) -> Option<String> {
|
||||
content_disposition
|
||||
let filename = field
|
||||
.content_disposition()
|
||||
.parameters
|
||||
.iter()
|
||||
.find_map(|param| match param {
|
||||
DispositionParam::Filename(filename) => Some(filename.clone()),
|
||||
_ => None,
|
||||
})
|
||||
});
|
||||
(mime, filename)
|
||||
}
|
||||
|
||||
fn get_content_type(bytes: &[u8]) -> Option<Mime> {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use actix_governor::governor::clock::{Clock, DefaultClock, QuantaInstant};
|
||||
use actix_governor::governor::NotUntil;
|
||||
use actix_governor::KeyExtractor;
|
||||
use actix_governor::PeerIpKeyExtractor;
|
||||
use actix_governor::SimpleKeyExtractionError;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::HttpResponseBuilder;
|
||||
use actix_web::{dev::ServiceRequest, http::header::ContentType};
|
||||
use std::net::{IpAddr, Ipv6Addr};
|
||||
use governor::clock::{Clock, DefaultClock, QuantaInstant};
|
||||
use governor::NotUntil;
|
||||
use std::net::IpAddr;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ForwardedPeerIpKeyExtractor {
|
||||
|
@ -19,15 +19,18 @@ impl KeyExtractor for ForwardedPeerIpKeyExtractor {
|
|||
|
||||
fn extract(&self, req: &ServiceRequest) -> Result<Self::Key, Self::KeyExtractionError> {
|
||||
let forwarded_for = req.headers().get("x-forwarded-for");
|
||||
let ip = if self.proxied && forwarded_for.is_some() {
|
||||
let mut ip = if self.proxied && forwarded_for.is_some() {
|
||||
read_forwareded_for(forwarded_for).map_err(SimpleKeyExtractionError::new)?
|
||||
} else {
|
||||
PeerIpKeyExtractor.extract(req)?
|
||||
};
|
||||
|
||||
if let IpAddr::V6(mut ipv6) = ip {
|
||||
// only keep the first /56 for IPv6 addresses
|
||||
ipv6 &= Ipv6Addr::from_bits(u128::MAX << (u128::BITS - 56));
|
||||
// only keep the first /56 for ipv6 addresses
|
||||
// mask 0xffff_ffff_ffff_ff00_0000_0000_0000_0000
|
||||
if let IpAddr::V6(ipv6) = ip {
|
||||
let mut octets = ipv6.octets();
|
||||
octets[7..16].fill(0);
|
||||
ip = IpAddr::V6(octets.into());
|
||||
}
|
||||
|
||||
Ok(ip)
|
||||
|
|
|
@ -4,7 +4,7 @@ use actix_web::{
|
|||
http::header::{HeaderValue, CONTENT_SECURITY_POLICY},
|
||||
Error, HttpMessage,
|
||||
};
|
||||
use actix_web::middleware::Next;
|
||||
use actix_web_lab::middleware::Next;
|
||||
use rand::Rng;
|
||||
use std::fmt::Display;
|
||||
|
||||
|
|
Loading…
Reference in New Issue