mirror of https://github.com/rwf2/Rocket.git
Use 'RelativePathBuf' as 'Config.temp_dir' type.
This makes a relative 'temp_dir' declared in a config file relative to the config file itself.
This commit is contained in:
parent
c3ee34e295
commit
76ec847a58
|
@ -46,7 +46,7 @@ atomic = "0.5"
|
||||||
parking_lot = "0.11"
|
parking_lot = "0.11"
|
||||||
ubyte = {version = "0.10", features = ["serde"] }
|
ubyte = {version = "0.10", features = ["serde"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
figment = { version = "0.10.4", features = ["toml", "env"] }
|
figment = { version = "0.10.6", features = ["toml", "env"] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
either = "1"
|
either = "1"
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
use figment::{Figment, Profile, Provider, Metadata, error::Result};
|
use figment::{Figment, Profile, Provider, Metadata, error::Result};
|
||||||
use figment::providers::{Serialized, Env, Toml, Format};
|
use figment::providers::{Serialized, Env, Toml, Format};
|
||||||
use figment::value::{Map, Dict};
|
use figment::value::{Map, Dict, magic::RelativePathBuf};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
|
||||||
|
@ -87,7 +86,8 @@ pub struct Config {
|
||||||
pub secret_key: SecretKey,
|
pub secret_key: SecretKey,
|
||||||
/// Directory to store temporary files in. **(default:
|
/// Directory to store temporary files in. **(default:
|
||||||
/// [`std::env::temp_dir()`])**
|
/// [`std::env::temp_dir()`])**
|
||||||
pub temp_dir: PathBuf,
|
#[serde(serialize_with = "RelativePathBuf::serialize_relative")]
|
||||||
|
pub temp_dir: RelativePathBuf,
|
||||||
/// Max level to log. **(default: _debug_ `normal` / _release_ `critical`)**
|
/// Max level to log. **(default: _debug_ `normal` / _release_ `critical`)**
|
||||||
pub log_level: LogLevel,
|
pub log_level: LogLevel,
|
||||||
/// Graceful shutdown configuration. **(default: [`Shutdown::default()`])**
|
/// Graceful shutdown configuration. **(default: [`Shutdown::default()`])**
|
||||||
|
@ -167,7 +167,7 @@ impl Config {
|
||||||
ident: Ident::default(),
|
ident: Ident::default(),
|
||||||
#[cfg(feature = "secrets")]
|
#[cfg(feature = "secrets")]
|
||||||
secret_key: SecretKey::zero(),
|
secret_key: SecretKey::zero(),
|
||||||
temp_dir: std::env::temp_dir(),
|
temp_dir: std::env::temp_dir().into(),
|
||||||
log_level: LogLevel::Normal,
|
log_level: LogLevel::Normal,
|
||||||
shutdown: Shutdown::default(),
|
shutdown: Shutdown::default(),
|
||||||
cli_colors: true,
|
cli_colors: true,
|
||||||
|
@ -335,7 +335,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_info_!("temp dir: {}", Paint::default(&self.temp_dir.display()).bold());
|
launch_info_!("temp dir: {}", Paint::default(&self.temp_dir.relative().display()).bold());
|
||||||
launch_info_!("log level: {}", Paint::default(self.log_level).bold());
|
launch_info_!("log level: {}", Paint::default(self.log_level).bold());
|
||||||
launch_info_!("cli colors: {}", Paint::default(&self.cli_colors).bold());
|
launch_info_!("cli colors: {}", Paint::default(&self.cli_colors).bold());
|
||||||
launch_info_!("shutdown: {}", Paint::default(&self.shutdown).bold());
|
launch_info_!("shutdown: {}", Paint::default(&self.shutdown).bold());
|
||||||
|
@ -369,6 +369,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Associated constants for default profiles.
|
||||||
impl Config {
|
impl Config {
|
||||||
/// The default debug profile: `debug`.
|
/// The default debug profile: `debug`.
|
||||||
pub const DEBUG_PROFILE: Profile = Profile::const_new("debug");
|
pub const DEBUG_PROFILE: Profile = Profile::const_new("debug");
|
||||||
|
@ -386,6 +387,7 @@ impl Config {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Associated constants for stringy versions of configuration parameters.
|
||||||
impl Config {
|
impl Config {
|
||||||
/// The stringy parameter name for setting/extracting [`Config::profile`].
|
/// The stringy parameter name for setting/extracting [`Config::profile`].
|
||||||
///
|
///
|
||||||
|
@ -421,6 +423,9 @@ impl Config {
|
||||||
|
|
||||||
/// The stringy parameter name for setting/extracting [`Config::shutdown`].
|
/// The stringy parameter name for setting/extracting [`Config::shutdown`].
|
||||||
pub const SHUTDOWN: &'static str = "shutdown";
|
pub const SHUTDOWN: &'static str = "shutdown";
|
||||||
|
|
||||||
|
/// The stringy parameter name for setting/extracting [`Config::cli_colors`].
|
||||||
|
pub const CLI_COLORS: &'static str = "cli_colors";
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Provider for Config {
|
impl Provider for Config {
|
||||||
|
|
|
@ -45,7 +45,7 @@ use either::Either;
|
||||||
///
|
///
|
||||||
/// | Name | Default | Description |
|
/// | Name | Default | Description |
|
||||||
/// |--------------------|---------------------|-----------------------------------------|
|
/// |--------------------|---------------------|-----------------------------------------|
|
||||||
/// | `temp_dir` | [`env::temp_dir()`] | Directory files are temporarily stored. |
|
/// | `temp_dir` | [`env::temp_dir()`] | Directory for temporary file storage. |
|
||||||
/// | `limits.file` | 1MiB | Default limit for all file extensions. |
|
/// | `limits.file` | 1MiB | Default limit for all file extensions. |
|
||||||
/// | `limits.file/$ext` | _N/A_ | Limit for files with extension `$ext`. |
|
/// | `limits.file/$ext` | _N/A_ | Limit for files with extension `$ext`. |
|
||||||
///
|
///
|
||||||
|
@ -451,7 +451,7 @@ impl<'v> TempFile<'v> {
|
||||||
.or_else(|| req.limits().get("file"))
|
.or_else(|| req.limits().get("file"))
|
||||||
.unwrap_or(Limits::FILE);
|
.unwrap_or(Limits::FILE);
|
||||||
|
|
||||||
let temp_dir = req.rocket().config().temp_dir.clone();
|
let temp_dir = req.rocket().config().temp_dir.relative();
|
||||||
let file = tokio::task::spawn_blocking(move || {
|
let file = tokio::task::spawn_blocking(move || {
|
||||||
NamedTempFile::new_in(temp_dir)
|
NamedTempFile::new_in(temp_dir)
|
||||||
}).await.map_err(|_| {
|
}).await.map_err(|_| {
|
||||||
|
|
|
@ -182,7 +182,7 @@ impl Rocket<Build> {
|
||||||
/// let config = Config {
|
/// let config = Config {
|
||||||
/// port: 7777,
|
/// port: 7777,
|
||||||
/// address: Ipv4Addr::new(18, 127, 0, 1).into(),
|
/// address: Ipv4Addr::new(18, 127, 0, 1).into(),
|
||||||
/// temp_dir: PathBuf::from("/tmp/config-example"),
|
/// temp_dir: "/tmp/config-example".into(),
|
||||||
/// ..Config::debug_default()
|
/// ..Config::debug_default()
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
|
@ -190,7 +190,7 @@ impl Rocket<Build> {
|
||||||
/// let rocket = rocket::custom(&config).ignite().await?;
|
/// let rocket = rocket::custom(&config).ignite().await?;
|
||||||
/// assert_eq!(rocket.config().port, 7777);
|
/// assert_eq!(rocket.config().port, 7777);
|
||||||
/// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1));
|
/// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1));
|
||||||
/// assert_eq!(rocket.config().temp_dir, Path::new("/tmp/config-example"));
|
/// assert_eq!(rocket.config().temp_dir.relative(), Path::new("/tmp/config-example"));
|
||||||
///
|
///
|
||||||
/// // Create a new figment which modifies _some_ keys the existing figment:
|
/// // Create a new figment which modifies _some_ keys the existing figment:
|
||||||
/// let figment = rocket.figment().clone()
|
/// let figment = rocket.figment().clone()
|
||||||
|
@ -203,7 +203,7 @@ impl Rocket<Build> {
|
||||||
///
|
///
|
||||||
/// assert_eq!(rocket.config().port, 8888);
|
/// assert_eq!(rocket.config().port, 8888);
|
||||||
/// assert_eq!(rocket.config().address, Ipv4Addr::new(171, 64, 200, 10));
|
/// assert_eq!(rocket.config().address, Ipv4Addr::new(171, 64, 200, 10));
|
||||||
/// assert_eq!(rocket.config().temp_dir, Path::new("/tmp/config-example"));
|
/// assert_eq!(rocket.config().temp_dir.relative(), Path::new("/tmp/config-example"));
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
use rocket::{Request, Route, Catcher, route, catcher};
|
use rocket::{Request, Route, Catcher, route, catcher};
|
||||||
use rocket::data::{Data, ToByteUnit};
|
use rocket::data::{Data, ToByteUnit};
|
||||||
use rocket::http::{Status, Method::{Get, Post}};
|
use rocket::http::{Status, Method::{Get, Post}};
|
||||||
|
@ -43,7 +41,8 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
|
||||||
return route::Outcome::failure(Status::BadRequest);
|
return route::Outcome::failure(Status::BadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = File::create(env::temp_dir().join("upload.txt")).await;
|
let path = req.rocket().config().temp_dir.relative().join("upload.txt");
|
||||||
|
let file = File::create(path).await;
|
||||||
if let Ok(file) = file {
|
if let Ok(file) = file {
|
||||||
if let Ok(n) = data.open(2.mebibytes()).stream_to(file).await {
|
if let Ok(n) = data.open(2.mebibytes()).stream_to(file).await {
|
||||||
return route::Outcome::from(req, format!("OK: {} bytes uploaded.", n));
|
return route::Outcome::from(req, format!("OK: {} bytes uploaded.", n));
|
||||||
|
@ -59,7 +58,8 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_upload<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {
|
fn get_upload<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {
|
||||||
route::Outcome::from(req, std::fs::File::open(env::temp_dir().join("upload.txt")).ok()).pin()
|
let path = req.rocket().config().temp_dir.relative().join("upload.txt");
|
||||||
|
route::Outcome::from(req, std::fs::File::open(path).ok()).pin()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_found_handler<'r>(_: Status, req: &'r Request) -> catcher::BoxFuture<'r> {
|
fn not_found_handler<'r>(_: Status, req: &'r Request) -> catcher::BoxFuture<'r> {
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
use std::{io, env};
|
use std::{io, env};
|
||||||
|
|
||||||
use rocket::tokio::fs;
|
use rocket::Config;
|
||||||
|
|
||||||
use rocket::data::Capped;
|
use rocket::data::Capped;
|
||||||
use rocket::fs::{NamedFile, TempFile};
|
use rocket::fs::{NamedFile, TempFile};
|
||||||
|
use rocket::tokio::fs;
|
||||||
|
|
||||||
// Upload your `big_file.dat` by POSTing it to /upload.
|
// Upload your `big_file.dat` by POSTing it to /upload.
|
||||||
// try `curl --data-binary @file.txt http://127.0.0.1:8000/stream/file`
|
// try `curl --data-binary @file.txt http://127.0.0.1:8000/stream/file`
|
||||||
|
@ -17,19 +17,19 @@ const FILENAME: &str = "big_file.dat";
|
||||||
|
|
||||||
// This is a *raw* file upload, _not_ a multipart upload!
|
// This is a *raw* file upload, _not_ a multipart upload!
|
||||||
#[post("/file", data = "<file>")]
|
#[post("/file", data = "<file>")]
|
||||||
async fn upload(mut file: Capped<TempFile<'_>>) -> io::Result<String> {
|
async fn upload(mut file: Capped<TempFile<'_>>, config: &Config) -> io::Result<String> {
|
||||||
file.persist_to(env::temp_dir().join(FILENAME)).await?;
|
file.persist_to(config.temp_dir.relative().join(FILENAME)).await?;
|
||||||
Ok(format!("{} bytes at {}", file.n.written, file.path().unwrap().display()))
|
Ok(format!("{} bytes at {}", file.n.written, file.path().unwrap().display()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/file")]
|
#[get("/file")]
|
||||||
async fn file() -> Option<NamedFile> {
|
async fn file(config: &Config) -> Option<NamedFile> {
|
||||||
NamedFile::open(env::temp_dir().join(FILENAME)).await.ok()
|
NamedFile::open(config.temp_dir.relative().join(FILENAME)).await.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/file")]
|
#[delete("/file")]
|
||||||
async fn delete() -> Option<()> {
|
async fn delete(config: &Config) -> Option<()> {
|
||||||
fs::remove_file(env::temp_dir().join(FILENAME)).await.ok()
|
fs::remove_file(config.temp_dir.relative().join(FILENAME)).await.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************** `Stream` Responder *****************************/
|
/***************************** `Stream` Responder *****************************/
|
||||||
|
|
Loading…
Reference in New Issue