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:
Sergio Benitez 2021-06-25 11:42:49 -07:00
parent c3ee34e295
commit 76ec847a58
6 changed files with 28 additions and 23 deletions

View File

@ -46,7 +46,7 @@ atomic = "0.5"
parking_lot = "0.11"
ubyte = {version = "0.10", features = ["serde"] }
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"
either = "1"
pin-project-lite = "0.2"

View File

@ -1,9 +1,8 @@
use std::path::PathBuf;
use std::net::{IpAddr, Ipv4Addr};
use figment::{Figment, Profile, Provider, Metadata, error::Result};
use figment::providers::{Serialized, Env, Toml, Format};
use figment::value::{Map, Dict};
use figment::value::{Map, Dict, magic::RelativePathBuf};
use serde::{Deserialize, Serialize};
use yansi::Paint;
@ -87,7 +86,8 @@ pub struct Config {
pub secret_key: SecretKey,
/// Directory to store temporary files in. **(default:
/// [`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`)**
pub log_level: LogLevel,
/// Graceful shutdown configuration. **(default: [`Shutdown::default()`])**
@ -167,7 +167,7 @@ impl Config {
ident: Ident::default(),
#[cfg(feature = "secrets")]
secret_key: SecretKey::zero(),
temp_dir: std::env::temp_dir(),
temp_dir: std::env::temp_dir().into(),
log_level: LogLevel::Normal,
shutdown: Shutdown::default(),
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_!("cli colors: {}", Paint::default(&self.cli_colors).bold());
launch_info_!("shutdown: {}", Paint::default(&self.shutdown).bold());
@ -369,6 +369,7 @@ impl Config {
}
}
/// Associated constants for default profiles.
impl Config {
/// The default debug profile: `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 {
/// The stringy parameter name for setting/extracting [`Config::profile`].
///
@ -421,6 +423,9 @@ impl Config {
/// The stringy parameter name for setting/extracting [`Config::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 {

View File

@ -45,7 +45,7 @@ use either::Either;
///
/// | 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/$ext` | _N/A_ | Limit for files with extension `$ext`. |
///
@ -451,7 +451,7 @@ impl<'v> TempFile<'v> {
.or_else(|| req.limits().get("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 || {
NamedTempFile::new_in(temp_dir)
}).await.map_err(|_| {

View File

@ -182,7 +182,7 @@ impl Rocket<Build> {
/// let config = Config {
/// port: 7777,
/// address: Ipv4Addr::new(18, 127, 0, 1).into(),
/// temp_dir: PathBuf::from("/tmp/config-example"),
/// temp_dir: "/tmp/config-example".into(),
/// ..Config::debug_default()
/// };
///
@ -190,7 +190,7 @@ impl Rocket<Build> {
/// let rocket = rocket::custom(&config).ignite().await?;
/// assert_eq!(rocket.config().port, 7777);
/// 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:
/// let figment = rocket.figment().clone()
@ -203,7 +203,7 @@ impl Rocket<Build> {
///
/// assert_eq!(rocket.config().port, 8888);
/// 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(())
/// # });
/// ```

View File

@ -1,8 +1,6 @@
#[cfg(test)]
mod tests;
use std::env;
use rocket::{Request, Route, Catcher, route, catcher};
use rocket::data::{Data, ToByteUnit};
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);
}
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(n) = data.open(2.mebibytes()).stream_to(file).await {
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> {
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> {

View File

@ -6,10 +6,10 @@
use std::{io, env};
use rocket::tokio::fs;
use rocket::Config;
use rocket::data::Capped;
use rocket::fs::{NamedFile, TempFile};
use rocket::tokio::fs;
// Upload your `big_file.dat` by POSTing it to /upload.
// 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!
#[post("/file", data = "<file>")]
async fn upload(mut file: Capped<TempFile<'_>>) -> io::Result<String> {
file.persist_to(env::temp_dir().join(FILENAME)).await?;
async fn upload(mut file: Capped<TempFile<'_>>, config: &Config) -> io::Result<String> {
file.persist_to(config.temp_dir.relative().join(FILENAME)).await?;
Ok(format!("{} bytes at {}", file.n.written, file.path().unwrap().display()))
}
#[get("/file")]
async fn file() -> Option<NamedFile> {
NamedFile::open(env::temp_dir().join(FILENAME)).await.ok()
async fn file(config: &Config) -> Option<NamedFile> {
NamedFile::open(config.temp_dir.relative().join(FILENAME)).await.ok()
}
#[delete("/file")]
async fn delete() -> Option<()> {
fs::remove_file(env::temp_dir().join(FILENAME)).await.ok()
async fn delete(config: &Config) -> Option<()> {
fs::remove_file(config.temp_dir.relative().join(FILENAME)).await.ok()
}
/***************************** `Stream` Responder *****************************/