Add 'serve::crate_relative!' for relative paths.

The macro generates crate-relative paths for easier serving of files
stored relative to the crate root.
This commit is contained in:
Sergio Benitez 2020-07-23 16:48:26 -07:00
parent 261cb400d1
commit a115eaa633
6 changed files with 61 additions and 23 deletions

View File

@ -21,6 +21,44 @@ use rocket::http::{Method, uri::Segments, ext::IntoOwned};
use rocket::handler::{Handler, Outcome};
use rocket::response::{NamedFile, Redirect};
/// Generates a crate-relative version of `$path`.
///
/// This macro is primarily intended for use with [`StaticFiles`] to serve files
/// from a path relative to the crate root. The macro accepts one parameter,
/// `$path`, an absolute or relative path. It returns a path (an `&'static str`)
/// prefixed with the path to the crate root. Use `Path::new()` to retrieve an
/// `&'static Path`.
///
/// See the [relative paths `StaticFiles`
/// documentation](`StaticFiles`#relative-paths) for an example.
///
/// # Example
///
/// ```rust
/// use rocket_contrib::serve::{StaticFiles, crate_relative};
///
/// let manual = concat!(env!("CARGO_MANIFEST_DIR"), "/static");
/// let automatic = crate_relative!("static");
/// assert_eq!(manual, automatic);
///
/// use std::path::Path;
///
/// let manual = Path::new(env!("CARGO_MANIFEST_DIR")).join("static");
/// let automatic_1 = Path::new(crate_relative!("static"));
/// let automatic_2 = Path::new(crate_relative!("/static"));
/// assert_eq!(manual, automatic_1);
/// assert_eq!(automatic_1, automatic_2);
/// ```
#[macro_export]
macro_rules! crate_relative {
($path:expr) => {
concat!(env!("CARGO_MANIFEST_DIR"), "/", $path)
};
}
#[doc(inline)]
pub use crate_relative;
/// A bitset representing configurable options for the [`StaticFiles`] handler.
///
/// The valid options are:
@ -146,22 +184,22 @@ impl std::ops::BitOr for Options {
/// `/public/<directory>` will be handled by returning the contents of
/// `/static/<directory>/index.html`.
///
/// `/static` is an absolute path. If your static files are stored relative to
/// your crate and your project is managed by Cargo, you should either use a
/// relative path and ensure that your server is started in the crate's root
/// directory or use the `CARGO_MANIFEST_DIR` environment variable to create an
/// absolute path relative to your crate root. For example, to serve files in
/// the `static` subdirectory of your crate at `/`, you might write:
/// ## Relative Paths
///
/// In the example above, `/static` is an absolute path. If your static files
/// are stored relative to your crate and your project is managed by Cargo, use
/// the [`crate_relative!`] macro to obtain a path that is relative to your
/// crate's root. For example, to serve files in the `static` subdirectory of
/// your crate at `/`, you might write:
///
/// ```rust,no_run
/// # #[macro_use] extern crate rocket;
/// # extern crate rocket_contrib;
/// use rocket_contrib::serve::StaticFiles;
/// use rocket_contrib::serve::{StaticFiles, crate_relative};
///
/// #[launch]
/// fn rocket() -> rocket::Rocket {
/// rocket::ignite()
/// .mount("/", StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static")))
/// rocket::ignite().mount("/", StaticFiles::from(crate_relative!("/static")))
/// }
/// ```
#[derive(Clone)]

View File

@ -1,17 +1,15 @@
#[cfg(feature = "serve")]
mod static_tests {
use std::{io::Read, fs::File};
use std::path::{Path, PathBuf};
use std::path::Path;
use rocket::{self, Rocket, Route};
use rocket_contrib::serve::{StaticFiles, Options};
use rocket_contrib::serve::{StaticFiles, Options, crate_relative};
use rocket::http::Status;
use rocket::local::blocking::Client;
fn static_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("static")
fn static_root() -> &'static Path {
Path::new(crate_relative!("/tests/static"))
}
fn rocket() -> Rocket {

View File

@ -3,7 +3,7 @@
use rocket::request::{Form, FormError, FormDataError};
use rocket::http::RawStr;
use rocket_contrib::serve::StaticFiles;
use rocket_contrib::serve::{StaticFiles, crate_relative};
#[cfg(test)] mod tests;
@ -37,5 +37,7 @@ fn sink(sink: Result<Form<FormInput<'_>>, FormError<'_>>) -> String {
#[launch]
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/", routes![sink]).mount("/", StaticFiles::from("static/"))
rocket::ignite()
.mount("/", routes![sink])
.mount("/", StaticFiles::from(crate_relative!("/static")))
}

View File

@ -6,7 +6,7 @@ use rocket::response::Redirect;
use rocket::request::{Form, FromFormValue};
use rocket::http::RawStr;
use rocket_contrib::serve::StaticFiles;
use rocket_contrib::serve::{StaticFiles, crate_relative};
#[derive(Debug)]
struct StrongPassword<'r>(&'r str);
@ -79,5 +79,5 @@ fn user_page(username: &RawStr) -> String {
fn rocket() -> rocket::Rocket {
rocket::ignite()
.mount("/", routes![user_page, login])
.mount("/", StaticFiles::from("static/"))
.mount("/", StaticFiles::from(crate_relative!("/static")))
}

View File

@ -2,7 +2,7 @@
#[cfg(test)] mod tests;
use rocket_contrib::serve::StaticFiles;
use rocket_contrib::serve::{StaticFiles, crate_relative};
// If we wanted or needed to serve files manually, we'd use `NamedFile`. Always
// prefer to use `StaticFiles`!
@ -19,5 +19,5 @@ mod manual {
fn rocket() -> rocket::Rocket {
rocket::ignite()
.mount("/", routes![manual::icon])
.mount("/", StaticFiles::from("static"))
.mount("/", StaticFiles::from(crate_relative!("/static")))
}

View File

@ -11,7 +11,7 @@ use rocket::Rocket;
use rocket::fairing::AdHoc;
use rocket::request::{Form, FlashMessage};
use rocket::response::{Flash, Redirect};
use rocket_contrib::{templates::Template, serve::StaticFiles};
use rocket_contrib::{templates::Template, serve::{StaticFiles, crate_relative}};
use diesel::SqliteConnection;
use crate::task::{Task, Todo};
@ -106,7 +106,7 @@ fn rocket() -> Rocket {
rocket::ignite()
.attach(DbConn::fairing())
.attach(AdHoc::on_attach("Database Migrations", run_db_migrations))
.mount("/", StaticFiles::from("static/"))
.mount("/", StaticFiles::from(crate_relative!("/static")))
.mount("/", routes![index])
.mount("/todo", routes![new, toggle, delete])
.attach(Template::fairing())