Compare commits
4 Commits
4a9a71b9f3
...
9e083907c7
Author | SHA1 | Date |
---|---|---|
minish | 9e083907c7 | |
minish | 6d86d4a081 | |
minish | b44fa6c4a1 | |
minish | b8611e6415 |
|
@ -38,18 +38,18 @@ checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.59"
|
version = "0.1.68"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.22",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -118,7 +118,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -135,9 +135,10 @@ dependencies = [
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
"axum",
|
"axum",
|
||||||
"bytes",
|
"bytes",
|
||||||
"env_logger",
|
"futures",
|
||||||
"hyper",
|
"hyper",
|
||||||
"log",
|
"log",
|
||||||
|
"pretty_env_logger",
|
||||||
"rand",
|
"rand",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
@ -214,58 +215,89 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
|
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
|
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
|
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
|
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.22",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
|
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
|
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.25"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
|
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
"futures-macro",
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"slab",
|
"slab",
|
||||||
|
@ -565,7 +597,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -587,19 +619,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "pretty_env_logger"
|
||||||
version = "1.0.47"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.63"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.21"
|
version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -784,6 +826,17 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sync_wrapper"
|
name = "sync_wrapper"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -827,7 +880,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -14,6 +14,7 @@ bytes = "1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
async-recursion = "1.0.0"
|
async-recursion = "1.0.0"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
futures = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.10.0"
|
pretty_env_logger = "0.5.0"
|
||||||
archived = { path = "./archived" }
|
archived = { path = "./archived" }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
@ -67,7 +67,7 @@ impl Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks in cache or disk for an upload using a pathbuf
|
// checks in cache or disk for an upload using a pathbuf
|
||||||
pub async fn upload_exists(&self, path: &PathBuf) -> bool {
|
pub async fn upload_exists(&self, path: &Path) -> bool {
|
||||||
let cache = self.cache.read().await;
|
let cache = self.cache.read().await;
|
||||||
|
|
||||||
// check if upload is in cache
|
// check if upload is in cache
|
||||||
|
@ -199,20 +199,20 @@ impl Engine {
|
||||||
async fn read_cached_upload(&self, name: &String) -> Option<Bytes> {
|
async fn read_cached_upload(&self, name: &String) -> Option<Bytes> {
|
||||||
let cache = self.cache.read().await;
|
let cache = self.cache.read().await;
|
||||||
|
|
||||||
if !cache.contains_key(&name) {
|
if !cache.contains_key(name) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch upload data from cache
|
// fetch upload data from cache
|
||||||
let data = cache
|
let data = cache
|
||||||
.get(&name)
|
.get(name)
|
||||||
.expect("failed to read get upload data from cache")
|
.expect("failed to read get upload data from cache")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
Some(data)
|
Some(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_upload(&self, original_path: &PathBuf) -> Result<ViewSuccess, ViewError> {
|
pub async fn get_upload(&self, original_path: &Path) -> Result<ViewSuccess, ViewError> {
|
||||||
// extract upload file name
|
// extract upload file name
|
||||||
let name = original_path
|
let name = original_path
|
||||||
.file_name()
|
.file_name()
|
||||||
|
@ -235,7 +235,7 @@ impl Engine {
|
||||||
if let Some(data) = cached_data {
|
if let Some(data) = cached_data {
|
||||||
info!("got upload from cache!!");
|
info!("got upload from cache!!");
|
||||||
|
|
||||||
return Ok(ViewSuccess::FromCache(data));
|
Ok(ViewSuccess::FromCache(data))
|
||||||
} else {
|
} else {
|
||||||
let mut file = File::open(&path).await.unwrap();
|
let mut file = File::open(&path).await.unwrap();
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ impl Engine {
|
||||||
|
|
||||||
info!("got upload from disk!");
|
info!("got upload from disk!");
|
||||||
|
|
||||||
return Ok(ViewSuccess::FromDisk(file));
|
Ok(ViewSuccess::FromDisk(file))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub async fn index(State(engine): State<Arc<crate::engine::Engine>>) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
// robots.txt that tells web crawlers not to list uploads
|
// robots.txt that tells web crawlers not to list uploads
|
||||||
const ROBOTS_TXT: &'static str = concat!(
|
const ROBOTS_TXT: &str = concat!(
|
||||||
"User-Agent: *\n",
|
"User-Agent: *\n",
|
||||||
"Disallow: /p/*\n",
|
"Disallow: /p/*\n",
|
||||||
"Allow: /\n"
|
"Allow: /\n"
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -21,7 +21,7 @@ mod view;
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// initialise logger
|
// initialise logger
|
||||||
env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
// read env vars
|
// read env vars
|
||||||
let base_url = env::var("BRZ_BASE_URL").expect("missing BRZ_BASE_URL! base url for upload urls (ex: http://127.0.0.1:8000 for http://127.0.0.1:8000/p/abcdef.png, http://picture.wtf for http://picture.wtf/p/abcdef.png)");
|
let base_url = env::var("BRZ_BASE_URL").expect("missing BRZ_BASE_URL! base url for upload urls (ex: http://127.0.0.1:8000 for http://127.0.0.1:8000/p/abcdef.png, http://picture.wtf for http://picture.wtf/p/abcdef.png)");
|
||||||
|
@ -34,10 +34,10 @@ async fn main() {
|
||||||
|
|
||||||
// parse env vars
|
// parse env vars
|
||||||
let save_path = PathBuf::from(save_path);
|
let save_path = PathBuf::from(save_path);
|
||||||
let cache_max_length = usize::from_str_radix(&cache_max_length, 10).expect("failed parsing BRZ_CACHE_UPL_MAX_LENGTH! it should be a positive number without any separators");
|
let cache_max_length = cache_max_length.parse::<usize>().expect("failed parsing BRZ_CACHE_UPL_MAX_LENGTH! it should be a positive number without any separators");
|
||||||
let cache_upl_lifetime = Duration::from_secs(u64::from_str_radix(&cache_upl_lifetime, 10).expect("failed parsing BRZ_CACHE_UPL_LIFETIME! it should be a positive number without any separators"));
|
let cache_upl_lifetime = Duration::from_secs(cache_upl_lifetime.parse::<u64>().expect("failed parsing BRZ_CACHE_UPL_LIFETIME! it should be a positive number without any separators"));
|
||||||
let cache_scan_freq = Duration::from_secs(u64::from_str_radix(&cache_scan_freq, 10).expect("failed parsing BRZ_CACHE_SCAN_FREQ! it should be a positive number without any separators"));
|
let cache_scan_freq = Duration::from_secs(cache_scan_freq.parse::<u64>().expect("failed parsing BRZ_CACHE_SCAN_FREQ! it should be a positive number without any separators"));
|
||||||
let cache_mem_capacity = usize::from_str_radix(&cache_mem_capacity, 10).expect("failed parsing BRZ_CACHE_MEM_CAPACITY! it should be a positive number without any separators");
|
let cache_mem_capacity = cache_mem_capacity.parse::<usize>().expect("failed parsing BRZ_CACHE_MEM_CAPACITY! it should be a positive number without any separators");
|
||||||
|
|
||||||
if !save_path.exists() || !save_path.is_dir() {
|
if !save_path.exists() || !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");
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub async fn new(
|
||||||
.get(header::CONTENT_LENGTH)
|
.get(header::CONTENT_LENGTH)
|
||||||
.unwrap_or(&HeaderValue::from_static(""))
|
.unwrap_or(&HeaderValue::from_static(""))
|
||||||
.to_str()
|
.to_str()
|
||||||
.and_then(|s| Ok(usize::from_str_radix(s, 10)))
|
.map(|s| s.parse::<usize>())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap_or(usize::MAX);
|
.unwrap_or(usize::MAX);
|
||||||
|
|
||||||
|
@ -51,6 +51,6 @@ pub async fn new(
|
||||||
engine
|
engine
|
||||||
.process_upload(path, name, content_length, stream)
|
.process_upload(path, name, content_length, stream)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(url)
|
Ok(url)
|
||||||
}
|
}
|
||||||
|
|
48
src/view.rs
48
src/view.rs
|
@ -10,8 +10,8 @@ use axum::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use hyper::StatusCode;
|
use hyper::{http::HeaderValue, StatusCode};
|
||||||
use tokio::fs::File;
|
use tokio::{fs::File, runtime::Handle};
|
||||||
use tokio_util::io::ReaderStream;
|
use tokio_util::io::ReaderStream;
|
||||||
|
|
||||||
pub enum ViewSuccess {
|
pub enum ViewSuccess {
|
||||||
|
@ -20,7 +20,7 @@ pub enum ViewSuccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ViewError {
|
pub enum ViewError {
|
||||||
NotFound, // 404
|
NotFound, // 404
|
||||||
InternalServerError, // 500
|
InternalServerError, // 500
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,48 @@ impl IntoResponse for ViewSuccess {
|
||||||
fn into_response(self) -> Response {
|
fn into_response(self) -> Response {
|
||||||
match self {
|
match self {
|
||||||
ViewSuccess::FromDisk(file) => {
|
ViewSuccess::FromDisk(file) => {
|
||||||
|
// get handle to current runtime
|
||||||
|
// i use this to block on futures here (not async)
|
||||||
|
let handle = Handle::current();
|
||||||
|
let _ = handle.enter();
|
||||||
|
|
||||||
|
// read the metadata of the file on disk
|
||||||
|
// this function isn't async
|
||||||
|
// .. so we have to use handle.block_on() to get the metadata
|
||||||
|
let metadata = futures::executor::block_on(file.metadata());
|
||||||
|
|
||||||
|
// if we error then return 500
|
||||||
|
if metadata.is_err() {
|
||||||
|
error!("failed to read metadata from disk");
|
||||||
|
return ViewError::InternalServerError.into_response();
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrap (which we know is safe) and read the file size as a string
|
||||||
|
let metadata = metadata.unwrap();
|
||||||
|
let len_str = metadata.len().to_string();
|
||||||
|
|
||||||
|
debug!("file is {} bytes on disk", &len_str);
|
||||||
|
|
||||||
|
// HeaderValue::from_str will never error if only visible ASCII characters are passed (32-127)
|
||||||
|
// .. so unwrapping this should be fine
|
||||||
|
let content_length = HeaderValue::from_str(&len_str).unwrap();
|
||||||
|
|
||||||
// create a streamed body response (we want to stream larger files)
|
// create a streamed body response (we want to stream larger files)
|
||||||
let reader = ReaderStream::new(file);
|
let reader = ReaderStream::new(file);
|
||||||
let stream = StreamBody::new(reader);
|
let stream = StreamBody::new(reader);
|
||||||
|
|
||||||
stream.into_response()
|
// extract mutable headers from the response
|
||||||
|
let mut res = stream.into_response();
|
||||||
|
let headers = res.headers_mut();
|
||||||
|
|
||||||
|
// clear headers, browser can imply content type
|
||||||
|
headers.clear();
|
||||||
|
|
||||||
|
// insert Content-Length header
|
||||||
|
// that way the browser shows how big a file is when it's being downloaded
|
||||||
|
headers.insert("Content-Length", content_length);
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
ViewSuccess::FromCache(data) => {
|
ViewSuccess::FromCache(data) => {
|
||||||
// extract mutable headers from the response
|
// extract mutable headers from the response
|
||||||
|
@ -61,7 +98,7 @@ impl IntoResponse for ViewError {
|
||||||
ViewError::InternalServerError => {
|
ViewError::InternalServerError => {
|
||||||
// convert string into response, change status code
|
// convert string into response, change status code
|
||||||
let mut res = "internal server error!".into_response();
|
let mut res = "internal server error!".into_response();
|
||||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -77,7 +114,6 @@ pub async fn view(
|
||||||
// (hopefully) prevent path traversal, just check for any non-file components
|
// (hopefully) prevent path traversal, just check for any non-file components
|
||||||
if original_path
|
if original_path
|
||||||
.components()
|
.components()
|
||||||
.into_iter()
|
|
||||||
.any(|x| !matches!(x, Component::Normal(_)))
|
.any(|x| !matches!(x, Component::Normal(_)))
|
||||||
{
|
{
|
||||||
warn!("a request attempted path traversal");
|
warn!("a request attempted path traversal");
|
||||||
|
|
Loading…
Reference in New Issue