diff --git a/Cargo.lock b/Cargo.lock index 934436523a9cc7e988451653a8b84671c69faa4e..226797f2b7dcc21cfa3dde0efef02ab890da7709 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1139,16 +1139,6 @@ dependencies = [ "version_check 0.9.3", ] -[[package]] -name = "gethostname" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" -dependencies = [ - "libc", - "winapi 0.3.9", -] - [[package]] name = "getrandom" version = "0.1.16" @@ -2120,7 +2110,6 @@ dependencies = [ "base64", "chrono", "derive_more", - "gethostname", "log", "sea-orm", "serde", diff --git a/Cargo.toml b/Cargo.toml index 4d77239ed5033b11dc668a30c6f70dafef01ff4b..03374cf717e03eb26a9b2b78388898f7e95a93bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,5 @@ log = "^0.4.14" url = "2.2.2" base64 = "^0.13.0" simple-logging = { version = "^2.0.2" } -gethostname = "0.2.1" strfmt = "^0.1.6" sea-orm = { version = "^0.4.2", features = ["runtime-async-std-rustls", "sqlx-all", "sqlx-chrono"] } \ No newline at end of file diff --git a/deploy/Dockerfile b/deploy/Dockerfile index ebd5b60e864844f045cedfb3a106313a9f6d1c82..596d2524d46de80164fe9ca69275b058b42280ad 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -13,7 +13,7 @@ RUN cargo chef cook --release --recipe-path recipe.json COPY . . RUN cargo build --release --bin rustus -FROM debian:buster-20211201-slim AS runtime +FROM debian:bullseye-20211201-slim AS runtime WORKDIR app COPY --from=builder /app/target/release/rustus /usr/local/bin/ ENTRYPOINT ["/usr/local/bin/rustus"] diff --git a/src/config.rs b/src/config.rs index 18e3ec9ee6f09e7f55732aacb3dc42461851d50e..804041998171b0e53fb629aa94e45334e5c75e1d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::env; use std::path::PathBuf; use chrono::{Datelike, Timelike}; @@ -83,6 +84,14 @@ pub struct RustusConf { #[structopt(long, default_value = "/files", env = "RUSTUS_URL")] pub url: String, + #[structopt( + long, + short = "mbs", + default_value = "262144", + env = "RUSTUS_MAX_BODY_SIZE" + )] + pub max_body_size: usize, + /// Enabled hooks for http events #[structopt(long, default_value = "pre-create,post-finish", env = "RUSTUS_HOOKS")] pub enabled_hooks: String, @@ -183,8 +192,6 @@ impl RustusConf { } pub fn dir_struct(&self) -> String { - let hostname = gethostname::gethostname(); - let now = chrono::Utc::now(); let mut vars: HashMap<String, String> = HashMap::new(); vars.insert("day".into(), now.day().to_string()); @@ -192,7 +199,9 @@ impl RustusConf { vars.insert("year".into(), now.year().to_string()); vars.insert("hour".into(), now.hour().to_string()); vars.insert("minute".into(), now.minute().to_string()); - vars.insert("hostname".into(), hostname.to_string_lossy().into()); + for (key, value) in env::vars() { + vars.insert(format!("env[{}]", key), value); + } strfmt::strfmt(self.storage_opts.dis_structure.as_str(), &vars) .unwrap_or_else(|_| "".into()) } diff --git a/src/main.rs b/src/main.rs index 78f5fec377106adaee54ce6faca66ad631f6b3e5..4870ec39201adb200179319fa0810653d97fc846 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,6 +64,7 @@ pub fn create_server( .wrap( middleware::DefaultHeaders::new() .header("Tus-Resumable", "1.0.0") + .header("Tus-Max-Size", app_conf.max_body_size.to_string()) .header("Tus-Version", "1.0.0"), ) .wrap(middleware::Logger::new("\"%r\" \"-\" \"%s\" \"%a\" \"%D\"")) @@ -89,7 +90,7 @@ pub fn create_server( if let Some(workers_count) = workers { server = server.workers(workers_count); } - server = server.server_hostname("meme"); + Ok(server.run()) } diff --git a/src/protocol/core/mod.rs b/src/protocol/core/mod.rs index 59a2f847ace6d8b63ea7eaab436130b45de2e215..312ea329d0dee4579886c2dc851fca5f1fef0f69 100644 --- a/src/protocol/core/mod.rs +++ b/src/protocol/core/mod.rs @@ -1,3 +1,4 @@ +use actix_web::web::PayloadConfig; use actix_web::{guard, middleware, web}; use crate::RustusConf; @@ -26,6 +27,8 @@ pub fn add_extension(web_app: &mut web::ServiceConfig, app_conf: &RustusConf) { // PATCH /base/{file_id} // Main URL for uploading files. web::resource(app_conf.file_url().as_str()) + // 10 MB chunks + .app_data(PayloadConfig::new(app_conf.max_body_size)) .name("core:write_bytes") .guard(guard::Patch()) .to(routes::write_bytes), diff --git a/src/protocol/core/routes.rs b/src/protocol/core/routes.rs index 02da1a043086516884b3ab385d8de9786204505f..3620b79a27f602bf53c051ce3c4e4c4242be6550 100644 --- a/src/protocol/core/routes.rs +++ b/src/protocol/core/routes.rs @@ -48,7 +48,7 @@ pub async fn write_bytes( storage: web::Data<Box<dyn Storage + Send + Sync>>, ) -> actix_web::Result<HttpResponse> { if !check_header(&request, "Content-Type", "application/offset+octet-stream") { - return Ok(HttpResponseBuilder::new(StatusCode::UNSUPPORTED_MEDIA_TYPE).body("")); + return Ok(HttpResponse::UnsupportedMediaType().body("")); } let offset = parse_header(&request, "Upload-Offset"); diff --git a/src/protocol/creation/routes.rs b/src/protocol/creation/routes.rs index 7b97ab272c67e1443eefb30f49ea05663fc468b4..2bd587d3deb9adafb72cc49760280d8a95f0c1e7 100644 --- a/src/protocol/creation/routes.rs +++ b/src/protocol/creation/routes.rs @@ -84,6 +84,9 @@ pub async fn create_file( .extensions_vec() .contains(&ProtocolExtensions::CreationWithUpload); if with_upload && !bytes.is_empty() { + if !check_header(&request, "Content-Type", "application/offset+octet-stream") { + return Ok(HttpResponse::BadRequest().body("")); + } // Writing first bytes. upload_offset = storage .add_bytes(file_id.as_str(), 0, bytes.bytes()) diff --git a/src/storages/mod.rs b/src/storages/mod.rs index 520e4ac3dbd915a50e7db99c1eda296b40ac5bf9..33bb9b0c989e5b68ce8e14e0d3b759c125611db5 100644 --- a/src/storages/mod.rs +++ b/src/storages/mod.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use actix_files::NamedFile; use async_trait::async_trait; - use derive_more::{Display, From}; use crate::errors::RustusResult; @@ -102,8 +101,8 @@ pub trait Storage { /// This method is used to generate unique file id, create file and store information about it. /// /// # Params - /// `file_size` - Size of a file. It may be None if size is deffered; - /// `metadata` - Optional file metainformation; + /// `file_size` - Size of a file. It may be None if size is deferred; + /// `metadata` - Optional file meta-information; async fn create_file( &self, file_size: Option<usize>,