Compare commits

...

4 Commits

Author SHA1 Message Date
minish a315baa258
config restructure + motd option 2023-12-07 13:31:27 -05:00
minish 2aa97e05b4
fix typo in ViewError::NotFound doc comment 2023-12-07 13:21:13 -05:00
minish 5f8adf023f
lower path traversal warning to an info
the new default log level is warning
so i don't want it to be possible to spam server logs on default config
2023-12-02 15:58:00 -05:00
minish d9f560677a
lol oops 2023-11-10 19:36:43 -05:00
11 changed files with 189 additions and 143 deletions

151
Cargo.lock generated
View File

@ -2,6 +2,21 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.7.6" version = "0.7.6"
@ -114,9 +129,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.6.1" version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum-core", "axum-core",
@ -141,16 +156,15 @@ dependencies = [
"sync_wrapper", "sync_wrapper",
"tokio", "tokio",
"tower", "tower",
"tower-http",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
] ]
[[package]] [[package]]
name = "axum-core" name = "axum-core"
version = "0.3.0" version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bytes", "bytes",
@ -165,14 +179,29 @@ dependencies = [
[[package]] [[package]]
name = "axum-macros" name = "axum-macros"
version = "0.3.0" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4df0fc33ada14a338b799002f7e8657711422b25d4e16afb032708d6b185621" checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.104", "syn 2.0.38",
]
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
] ]
[[package]] [[package]]
@ -471,10 +500,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "h2" name = "gimli"
version = "0.3.15" version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "h2"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -482,7 +517,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"http", "http",
"indexmap 1.9.2", "indexmap 2.0.2",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
@ -527,9 +562,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.8" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -547,12 +582,6 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "http-range-header"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.8.0" version = "1.8.0"
@ -567,9 +596,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.23" version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -642,9 +671,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.4" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
@ -663,9 +692,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.137" version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -705,15 +734,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]] [[package]]
name = "mio" name = "miniz_oxide"
version = "0.8.5" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [ dependencies = [
"libc", "libc",
"log",
"wasi", "wasi",
"windows-sys 0.42.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -745,6 +782,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.16.0"
@ -887,6 +933,12 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.9" version = "1.0.9"
@ -1039,9 +1091,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.7" version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
@ -1122,14 +1174,14 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.22.0" version = "1.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"backtrace",
"bytes", "bytes",
"libc", "libc",
"memchr",
"mio", "mio",
"num_cpus", "num_cpus",
"parking_lot", "parking_lot",
@ -1137,18 +1189,18 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"winapi", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "1.8.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.104", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -1230,25 +1282,6 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "tower-http"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba"
dependencies = [
"bitflags",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-range-header",
"pin-project-lite",
"tower",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "tower-layer" name = "tower-layer"
version = "0.3.2" version = "0.3.2"

View File

@ -15,7 +15,7 @@ I wrote breeze with the intention of running it in a container, but it runs just
Either way, you need to start off by cloning the Git repository. Either way, you need to start off by cloning the Git repository.
```bash ```bash
git clone https://git.min.rip/minish/breeze.git git clone https://git.min.rip/min/breeze.git
``` ```
To run it in Docker, I recommend using Docker Compose. An example `docker-compose.yaml` configuration is below. To run it in Docker, I recommend using Docker Compose. An example `docker-compose.yaml` configuration is below.

7
archived/Cargo.lock generated
View File

@ -8,6 +8,7 @@ version = "0.2.0"
dependencies = [ dependencies = [
"bytes", "bytes",
"once_cell", "once_cell",
"rustc-hash",
] ]
[[package]] [[package]]
@ -21,3 +22,9 @@ name = "once_cell"
version = "1.3.1" version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"

View File

@ -6,4 +6,4 @@ license = "MIT"
[dependencies] [dependencies]
bytes = "1.3.0" bytes = "1.3.0"
once_cell = "1.3.1" once_cell = "1.3.1"

View File

@ -29,7 +29,11 @@ impl Archive {
} }
} */ } */
pub fn with_full_scan(full_scan_frequency: Duration, entry_lifetime: Duration, capacity: usize) -> Self { pub fn with_full_scan(
full_scan_frequency: Duration,
entry_lifetime: Duration,
capacity: usize,
) -> Self {
Self { Self {
cache_table: HashMap::with_capacity(256), cache_table: HashMap::with_capacity(256),
full_scan_frequency: Some(full_scan_frequency), full_scan_frequency: Some(full_scan_frequency),
@ -67,11 +71,7 @@ impl Archive {
.map(|cache_entry| &cache_entry.value) .map(|cache_entry| &cache_entry.value)
} }
pub fn get_or_insert<F>( pub fn get_or_insert<F>(&mut self, key: String, factory: F) -> &Bytes
&mut self,
key: String,
factory: F,
) -> &Bytes
where where
F: Fn() -> Bytes, F: Fn() -> Bytes,
{ {
@ -87,15 +87,15 @@ impl Archive {
&occupied.into_mut().value &occupied.into_mut().value
} }
Entry::Vacant(vacant) => &vacant.insert(CacheEntry::new(factory(), self.entry_lifetime)).value, Entry::Vacant(vacant) => {
&vacant
.insert(CacheEntry::new(factory(), self.entry_lifetime))
.value
}
} }
} }
pub fn insert( pub fn insert(&mut self, key: String, value: Bytes) -> Option<Bytes> {
&mut self,
key: String,
value: Bytes,
) -> Option<Bytes> {
let now = SystemTime::now(); let now = SystemTime::now();
self.try_full_scan_expired_items(now); self.try_full_scan_expired_items(now);
@ -144,7 +144,7 @@ impl Archive {
Some(()) Some(())
} }
None => None None => None,
} }
} }

View File

@ -7,7 +7,7 @@ use tracing_subscriber::filter::LevelFilter;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Config { pub struct Config {
pub engine: EngineConfig, pub engine: EngineConfig,
pub cache: CacheConfig, pub http: HttpConfig,
pub logger: LoggerConfig, pub logger: LoggerConfig,
} }
@ -22,7 +22,18 @@ pub struct EngineConfig {
pub save_path: PathBuf, pub save_path: PathBuf,
/// Authentication key for new uploads, will be required if this is specified. (optional) /// Authentication key for new uploads, will be required if this is specified. (optional)
pub upload_key: Option<String>, #[serde(default)]
pub upload_key: String,
/// Configuration for cache system
pub cache: CacheConfig,
/// Motd displayed when the server's index page is visited.
///
/// This isn't explicitly engine-related but the engine is what gets passed to routes,
/// so it is here for now.
#[serde(default = "default_motd")]
pub motd: String,
} }
#[serde_as] #[serde_as]
@ -45,11 +56,26 @@ pub struct CacheConfig {
pub mem_capacity: usize, pub mem_capacity: usize,
} }
fn default_motd() -> String {
"breeze file server (v%version%) - currently hosting %uplcount% files".to_string()
}
#[derive(Deserialize)]
pub struct HttpConfig {
pub listen_on: String,
}
fn default_level_filter() -> LevelFilter {
LevelFilter::WARN
}
#[serde_as] #[serde_as]
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct LoggerConfig { pub struct LoggerConfig {
/// Minimum level a log must be for it to be shown. /// Minimum level a log must be for it to be shown.
/// This defaults to "warn" if not specified. /// This defaults to "warn" if not specified.
#[serde_as(as = "Option<DisplayFromStr>")] #[serde_as(as = "DisplayFromStr")]
pub level: Option<LevelFilter>, #[serde(default = "default_level_filter")]
// yes... kind of a hack but serde doesn't have anything better
pub level: LevelFilter,
} }

View File

@ -2,7 +2,6 @@ use std::{
ffi::OsStr, ffi::OsStr,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
time::Duration,
}; };
use archived::Archive; use archived::Archive;
@ -21,66 +20,47 @@ use tokio_stream::StreamExt;
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::view::{ViewError, ViewSuccess}; use crate::{
config,
view::{ViewError, ViewSuccess},
};
/// breeze engine! this is the core of everything /// breeze engine! this is the core of everything
pub struct Engine { pub struct Engine {
// ------ STATE ------ //
/// The in-memory cache that cached uploads are stored in. /// The in-memory cache that cached uploads are stored in.
cache: RwLock<Archive>, cache: RwLock<Archive>,
/// Cached count of uploaded files. /// Cached count of uploaded files.
pub upl_count: AtomicUsize, pub upl_count: AtomicUsize,
// ------ CONFIG ------ // /// Engine configuration
/// The base URL that the server will be accessed from. pub cfg: config::EngineConfig,
/// It is only used for formatting returned upload URLs.
pub base_url: String,
/// The path on disk that uploads are saved to.
save_path: PathBuf,
/// The authorisation key required for uploading new files.
/// If it is empty, no key will be required.
pub upload_key: String,
/// The maximum size for an upload to be stored in cache.
/// Anything bigger skips cache and is read/written to
/// directly from disk.
cache_max_length: usize,
} }
impl Engine { impl Engine {
/// Creates a new instance of the breeze engine. /// Creates a new instance of the breeze engine.
pub fn new( pub fn new(cfg: config::EngineConfig) -> Self {
base_url: String,
save_path: PathBuf,
upload_key: String,
cache_max_length: usize,
cache_lifetime: Duration,
cache_full_scan_freq: Duration, // how often the cache will be scanned for expired items
cache_mem_capacity: usize,
) -> Self {
Self { Self {
cache: RwLock::new(Archive::with_full_scan( cache: RwLock::new(Archive::with_full_scan(
cache_full_scan_freq, cfg.cache.scan_freq,
cache_lifetime, cfg.cache.upload_lifetime,
cache_mem_capacity, cfg.cache.mem_capacity,
)), )),
upl_count: AtomicUsize::new(WalkDir::new(&save_path).min_depth(1).into_iter().count()), // count the amount of files in the save path and initialise our cached count with it upl_count: AtomicUsize::new(
WalkDir::new(&cfg.save_path)
.min_depth(1)
.into_iter()
.count(),
), // count the amount of files in the save path and initialise our cached count with it
base_url, cfg,
save_path,
upload_key,
cache_max_length,
} }
} }
/// Returns if an upload would be able to be cached /// Returns if an upload would be able to be cached
#[inline(always)] #[inline(always)]
fn will_use_cache(&self, length: usize) -> bool { fn will_use_cache(&self, length: usize) -> bool {
length <= self.cache_max_length length <= self.cfg.cache.max_length
} }
/// Check if an upload exists in cache or on disk /// Check if an upload exists in cache or on disk
@ -128,7 +108,7 @@ impl Engine {
.to_string(); .to_string();
// path on disk // path on disk
let mut path = self.save_path.clone(); let mut path = self.cfg.save_path.clone();
path.push(&id); path.push(&id);
path.set_extension(original_extension); path.set_extension(original_extension);
@ -238,7 +218,7 @@ impl Engine {
.to_string(); .to_string();
// path on disk // path on disk
let mut path = self.save_path.clone(); let mut path = self.cfg.save_path.clone();
path.push(&name); path.push(&name);
// check if the upload exists, if not then 404 // check if the upload exists, if not then 404

View File

@ -6,7 +6,11 @@ use axum::extract::State;
pub async fn index(State(engine): State<Arc<crate::engine::Engine>>) -> String { pub async fn index(State(engine): State<Arc<crate::engine::Engine>>) -> String {
let count = engine.upl_count.load(Ordering::Relaxed); let count = engine.upl_count.load(Ordering::Relaxed);
format!("minish's image host, currently hosting {} files", count) let motd = engine.cfg.motd.clone();
motd
.replace("%version%", env!("CARGO_PKG_VERSION"))
.replace("%uplcount%", &count.to_string())
} }
pub async fn robots_txt() -> &'static str { pub async fn robots_txt() -> &'static str {

View File

@ -11,7 +11,6 @@ use axum::{
}; };
use tokio::{fs, signal}; use tokio::{fs, signal};
use tracing::{info, warn}; use tracing::{info, warn};
use tracing_subscriber::filter::LevelFilter;
mod config; mod config;
mod engine; mod engine;
@ -35,30 +34,22 @@ async fn main() {
.await .await
.expect("failed to read config file! make sure it exists and you have read permissions"); .expect("failed to read config file! make sure it exists and you have read permissions");
let c: config::Config = toml::from_str(&config_str).expect("invalid config! check that you have included all required options and structured it properly (no config options expecting a number getting a string, etc.)"); let cfg: config::Config = toml::from_str(&config_str).expect("invalid config! check that you have included all required options and structured it properly (no config options expecting a number getting a string, etc.)");
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_max_level(c.logger.level.unwrap_or(LevelFilter::WARN)) .with_max_level(cfg.logger.level)
.init(); .init();
if !c.engine.save_path.exists() || !c.engine.save_path.is_dir() { if !cfg.engine.save_path.exists() || !cfg.engine.save_path.is_dir() {
panic!("the save path does not exist or is not a directory! this is invalid"); panic!("the save path does not exist or is not a directory! this is invalid");
} }
if c.engine.upload_key.is_none() { if cfg.engine.upload_key.is_empty() {
warn!("engine upload_key is empty! no key will be required for uploading new files"); warn!("engine upload_key is empty! no key will be required for uploading new files");
} }
// create engine // create engine
let engine = Engine::new( let engine = Engine::new(cfg.engine);
c.engine.base_url,
c.engine.save_path,
c.engine.upload_key.unwrap_or_default(),
c.cache.max_length,
c.cache.upload_lifetime,
c.cache.scan_freq,
c.cache.mem_capacity,
);
// build main router // build main router
let app = Router::new() let app = Router::new()
@ -69,11 +60,16 @@ async fn main() {
.with_state(Arc::new(engine)); .with_state(Arc::new(engine));
// start web server // start web server
axum::Server::bind(&"0.0.0.0:8000".parse().unwrap()) axum::Server::bind(
.serve(app.into_make_service()) &cfg.http
.with_graceful_shutdown(shutdown_signal()) .listen_on
.await .parse()
.unwrap(); .expect("failed to parse listen_on address"),
)
.serve(app.into_make_service())
.with_graceful_shutdown(shutdown_signal())
.await
.expect("failed to start server");
} }
async fn shutdown_signal() { async fn shutdown_signal() {

View File

@ -20,7 +20,7 @@ pub async fn new(
const EMPTY_STRING: &String = &String::new(); const EMPTY_STRING: &String = &String::new();
// check upload key, if i need to // check upload key, if i need to
if !engine.upload_key.is_empty() && key.unwrap_or(EMPTY_STRING) != &engine.upload_key { if !engine.cfg.upload_key.is_empty() && key.unwrap_or(EMPTY_STRING) != &engine.cfg.upload_key {
return Err(StatusCode::FORBIDDEN); return Err(StatusCode::FORBIDDEN);
} }
@ -40,7 +40,7 @@ pub async fn new(
.unwrap_or_default() .unwrap_or_default()
.to_string(); .to_string();
let url = format!("{}/p/{}", engine.base_url, name); let url = format!("{}/p/{}", engine.cfg.base_url, name);
// read and parse content-length, and if it fails just assume it's really high so it doesn't cache // read and parse content-length, and if it fails just assume it's really high so it doesn't cache
let content_length = headers let content_length = headers

View File

@ -13,7 +13,7 @@ use bytes::Bytes;
use hyper::{http::HeaderValue, StatusCode}; use hyper::{http::HeaderValue, StatusCode};
use tokio::{fs::File, runtime::Handle}; use tokio::{fs::File, runtime::Handle};
use tokio_util::io::ReaderStream; use tokio_util::io::ReaderStream;
use tracing::{error, debug, warn}; use tracing::{error, debug, info};
/// Responses for a successful view operation /// Responses for a successful view operation
pub enum ViewSuccess { pub enum ViewSuccess {
@ -38,7 +38,7 @@ pub enum ViewSuccess {
/// Responses for a failed view operation /// Responses for a failed view operation
pub enum ViewError { pub enum ViewError {
/// Will send status code 404 witha plaintext "not found" message. /// Will send status code 404 with a plaintext "not found" message.
NotFound, NotFound,
/// Will send status code 500 with a plaintext "internal server error" message. /// Will send status code 500 with a plaintext "internal server error" message.
@ -134,7 +134,7 @@ pub async fn view(
.components() .components()
.any(|x| !matches!(x, Component::Normal(_))) .any(|x| !matches!(x, Component::Normal(_)))
{ {
warn!("a request attempted path traversal"); info!("a request attempted path traversal");
return Err(ViewError::NotFound); return Err(ViewError::NotFound);
} }