Skip to content

Commit

Permalink
Merge branch 'SergioBenitez:master' into fix_issue_1224
Browse files Browse the repository at this point in the history
  • Loading branch information
jespersm authored Nov 10, 2023
2 parents 2a2272e + 1563718 commit 35669cc
Show file tree
Hide file tree
Showing 96 changed files with 1,002 additions and 593 deletions.
2 changes: 1 addition & 1 deletion contrib/db_pools/codegen/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream {
) -> rocket::request::Outcome<Self, Self::Error> {
match #db_ty::fetch(req.rocket()) {
Some(db) => rocket::outcome::Outcome::Success(db),
None => rocket::outcome::Outcome::Failure((
None => rocket::outcome::Outcome::Error((
rocket::http::Status::InternalServerError, ()))
}
}
Expand Down
6 changes: 3 additions & 3 deletions contrib/db_pools/lib/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ pub struct Initializer<D: Database>(Option<&'static str>, PhantomData<fn() -> D>
/// [`connect_timeout`](crate::Config::connect_timeout) seconds.
/// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with
/// status `InternalServerError`. A [`Sentinel`] guards this condition, and so
/// this type of failure is unlikely to occur. A `None` error is returned.
/// this type of error is unlikely to occur. A `None` error is returned.
/// * If a connection is not available within `connect_timeout` seconds or
/// another error occurs, the guard _fails_ with status `ServiceUnavailable`
/// and the error is returned in `Some`.
Expand Down Expand Up @@ -288,9 +288,9 @@ impl<'r, D: Database> FromRequest<'r> for Connection<D> {
match D::fetch(req.rocket()) {
Some(db) => match db.get().await {
Ok(conn) => Outcome::Success(Connection(conn)),
Err(e) => Outcome::Failure((Status::ServiceUnavailable, Some(e))),
Err(e) => Outcome::Error((Status::ServiceUnavailable, Some(e))),
},
None => Outcome::Failure((Status::InternalServerError, None)),
None => Outcome::Error((Status::InternalServerError, None)),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions contrib/dyn_templates/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ tera = ["tera_"]
handlebars = ["handlebars_"]

[dependencies]
glob = "0.3"
notify = "5.0.0"
walkdir = "2.4"
notify = "6"
normpath = "1"

[dependencies.rocket]
Expand Down
33 changes: 22 additions & 11 deletions contrib/dyn_templates/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ impl Context {
/// template engine, and store all of the initialized state in a `Context`
/// structure, which is returned if all goes well.
pub fn initialize(root: &Path, callback: &Callback) -> Option<Context> {
fn is_file_with_ext(entry: &walkdir::DirEntry, ext: &str) -> bool {
let is_file = entry.file_type().is_file();
let has_ext = entry.path().extension().map_or(false, |e| e == ext);
is_file && has_ext
}

let root = match root.normalize() {
Ok(root) => root.into_path_buf(),
Err(e) => {
Expand All @@ -35,18 +41,23 @@ impl Context {
};

let mut templates: HashMap<String, TemplateInfo> = HashMap::new();
for ext in Engines::ENABLED_EXTENSIONS {
let mut glob_path = root.join("**").join("*");
glob_path.set_extension(ext);
let glob_path = glob_path.to_str().expect("valid glob path string");
for &ext in Engines::ENABLED_EXTENSIONS {
for entry in walkdir::WalkDir::new(&root).follow_links(true) {
let entry = match entry {
Ok(entry) if is_file_with_ext(&entry, ext) => entry,
Ok(_) | Err(_) => continue,
};

for path in glob::glob(glob_path).unwrap().filter_map(Result::ok) {
let (name, data_type_str) = split_path(&root, &path);
let (name, data_type_str) = split_path(&root, entry.path());
if let Some(info) = templates.get(&*name) {
warn_!("Template name '{}' does not have a unique path.", name);
info_!("Existing path: {:?}", info.path);
info_!("Additional path: {:?}", path);
warn_!("Using existing path for template '{}'.", name);
warn_!("Template name '{}' does not have a unique source.", name);
match info.path {
Some(ref path) => info_!("Existing path: {:?}", path),
None => info_!("Existing Content-Type: {}", info.data_type),
}

info_!("Additional path: {:?}", entry.path());
warn_!("Keeping existing template '{}'.", name);
continue;
}

Expand All @@ -55,7 +66,7 @@ impl Context {
.unwrap_or(ContentType::Text);

templates.insert(name, TemplateInfo {
path: Some(path.clone()),
path: Some(entry.into_path()),
engine_ext: ext,
data_type,
});
Expand Down
2 changes: 1 addition & 1 deletion contrib/dyn_templates/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl<'r> FromRequest<'r> for Metadata<'r> {
error_!("Uninitialized template context: missing fairing.");
info_!("To use templates, you must attach `Template::fairing()`.");
info_!("See the `Template` documentation for more information.");
request::Outcome::Failure((Status::InternalServerError, ()))
request::Outcome::Error((Status::InternalServerError, ()))
})
}
}
10 changes: 10 additions & 0 deletions contrib/dyn_templates/tests/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ mod tera_tests {
assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));
}

#[async_test]
async fn test_globby_paths() {
use rocket::local::asynchronous::Client;

let client = Client::debug(rocket()).await.unwrap();
let req = client.get("/");
let metadata = Metadata::from_request(&req).await.unwrap();
assert!(metadata.contains_template("tera/[test]/html_test"));
}

// u128 is not supported. enable when it is.
// #[test]
// fn test_tera_u128() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "tera/base" %}
{% block title %}{{ title }}{% endblock title %}
{% block content %}
{{ content }}
{% endblock content %}
4 changes: 2 additions & 2 deletions contrib/sync_db_pools/lib/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ impl<'r, K: 'static, C: Poolable> FromRequest<'r> for Connection<K, C> {
#[inline]
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> {
match request.rocket().state::<ConnectionPool<K, C>>() {
Some(c) => c.get().await.into_outcome((Status::ServiceUnavailable, ())),
Some(c) => c.get().await.or_error((Status::ServiceUnavailable, ())),
None => {
error_!("Missing database fairing for `{}`", std::any::type_name::<K>());
Outcome::Failure((Status::InternalServerError, ()))
Outcome::Error((Status::InternalServerError, ()))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion contrib/ws/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ default = ["tungstenite"]
tungstenite = ["tokio-tungstenite"]

[dependencies]
tokio-tungstenite = { version = "0.19", optional = true }
tokio-tungstenite = { version = "0.20", optional = true }

[dependencies.rocket]
version = "=0.5.0-rc.3"
Expand Down
2 changes: 1 addition & 1 deletion contrib/ws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ This crate provides WebSocket support for Rocket via integration with Rocket's
```rust
#[get("/echo")]
fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {
ws::stream! { ws =>
ws::Stream! { ws =>
for await message in ws {
yield message?;
}
Expand Down
4 changes: 2 additions & 2 deletions contrib/ws/src/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::result::{Result, Error};
/// ### Forwarding
///
/// If the incoming request is not a valid WebSocket request, the guard
/// forwards. The guard never fails.
/// forwards with a status of `BadRequest`. The guard never fails.
pub struct WebSocket {
config: Config,
key: String,
Expand Down Expand Up @@ -203,7 +203,7 @@ impl<'r> FromRequest<'r> for WebSocket {
let key = headers.get_one("Sec-WebSocket-Key").map(|k| derive_accept_key(k.as_bytes()));
match key {
Some(key) if is_upgrade && is_ws && is_13 => Outcome::Success(WebSocket::new(key)),
Some(_) | None => Outcome::Forward(Status::NotFound)
Some(_) | None => Outcome::Forward(Status::BadRequest)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion core/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ rust-version = "1.56"
proc-macro = true

[dependencies]
indexmap = "1.0"
indexmap = "2"
quote = "1.0"
syn = { version = "2.0", features = ["full", "visit", "visit-mut", "extra-traits"] }
proc-macro2 = "1.0.27"
devise = "0.4"
rocket_http = { version = "=0.5.0-rc.3", path = "../http/" }
unicode-xid = "0.2"
version_check = "0.9"
glob = "0.3"

[dev-dependencies]
Expand Down
16 changes: 9 additions & 7 deletions core/codegen/src/attribute/route/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::proc_macro_ext::StringLit;
use crate::syn_ext::{IdentExt, TypeExt as _};
use crate::http_codegen::{Method, Optional};
use crate::attribute::param::Guard;
use crate::exports::mixed;

use self::parse::{Route, Attribute, MethodAttribute};

Expand Down Expand Up @@ -104,7 +105,7 @@ fn query_decls(route: &Route) -> Option<TokenStream> {
if !__e.is_empty() {
#_log::warn_!("Query string failed to match route declaration.");
for _err in __e { #_log::warn_!("{}", _err); }
return #Outcome::Forward((#__data, #Status::NotFound));
return #Outcome::Forward((#__data, #Status::UnprocessableEntity));
}

(#(#ident.unwrap()),*)
Expand All @@ -125,9 +126,9 @@ fn request_guard_decl(guard: &Guard) -> TokenStream {
#_log::warn_!("Request guard `{}` is forwarding.", stringify!(#ty));
return #Outcome::Forward((#__data, __e));
},
#Outcome::Failure((__c, __e)) => {
#Outcome::Error((__c, __e)) => {
#_log::warn_!("Request guard `{}` failed: {:?}.", stringify!(#ty), __e);
return #Outcome::Failure(__c);
return #Outcome::Error(__c);
}
};
}
Expand All @@ -145,7 +146,7 @@ fn param_guard_decl(guard: &Guard) -> TokenStream {
#_log::warn_!("Parameter guard `{}: {}` is forwarding: {:?}.",
#name, stringify!(#ty), __error);

#Outcome::Forward((#__data, #Status::NotFound))
#Outcome::Forward((#__data, #Status::UnprocessableEntity))
});

// All dynamic parameters should be found if this function is being called;
Expand Down Expand Up @@ -188,9 +189,9 @@ fn data_guard_decl(guard: &Guard) -> TokenStream {
#_log::warn_!("Data guard `{}` is forwarding.", stringify!(#ty));
return #Outcome::Forward((__d, __e));
}
#Outcome::Failure((__c, __e)) => {
#Outcome::Error((__c, __e)) => {
#_log::warn_!("Data guard `{}` failed: {:?}.", stringify!(#ty), __e);
return #Outcome::Failure(__c);
return #Outcome::Error(__c);
}
};
}
Expand Down Expand Up @@ -224,6 +225,7 @@ fn internal_uri_macro_decl(route: &Route) -> TokenStream {
}

#[doc(hidden)]
#[allow(unused)]
pub use #inner_macro_name as #macro_name;
}
}
Expand All @@ -242,7 +244,7 @@ fn responder_outcome_expr(route: &Route) -> TokenStream {
.map(|a| quote_spanned!(a.span() => .await));

define_spanned_export!(ret_span => __req, _route);
quote_spanned! { ret_span =>
quote_spanned! { mixed(ret_span) =>
let ___responder = #user_handler_fn_name(#(#parameter_names),*) #_await;
#_route::Outcome::from(#__req, ___responder)
}
Expand Down
26 changes: 18 additions & 8 deletions core/codegen/src/bang/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ pub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {
})
.collect();

// Only try using the `macro` syntax on nightly/dev or when we don't know.
let export = match version_check::is_feature_flaggable() {
Some(true) | None => quote! {
#(#attrs)*
#[cfg(all(nightly, doc))]
pub macro #macro_name {
#decl_macro_tokens
}

#[cfg(not(all(nightly, doc)))]
pub use #mod_name::#internal_name as #macro_name;
},
Some(false) => quote! {
pub use #mod_name::#internal_name as #macro_name;
}
};

Ok(quote! {
#[allow(non_snake_case)]
mod #mod_name {
Expand All @@ -43,13 +60,6 @@ pub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {
pub use #internal_name;
}

#(#attrs)*
#[cfg(all(nightly, doc))]
pub macro #macro_name {
#decl_macro_tokens
}

#[cfg(not(all(nightly, doc)))]
pub use #mod_name::#internal_name as #macro_name;
#export
})
}
2 changes: 1 addition & 1 deletion core/codegen/src/bang/uri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn add_binding<P: fmt::Part>(to: &mut Vec<TokenStream>, ident: &Ident, ty: &Type
let tmp_ident = ident.clone().with_span(expr.span());
let let_stmt = quote_spanned!(span => let #tmp_ident = #expr);

to.push(quote_spanned!(span =>
to.push(quote_spanned!(mixed(span) =>
#[allow(non_snake_case)] #let_stmt;
let #ident = <#ty as #_fmt::FromUriParam<#part, _>>::from_uri_param(#tmp_ident);
));
Expand Down
2 changes: 1 addition & 1 deletion core/codegen/src/bang/uri_parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl Arg {
fn unnamed(&self) -> &ArgExpr {
match self {
Arg::Unnamed(expr) => expr,
_ => panic!("Called Arg::unnamed() on an Arg::named!"),
_ => panic!("Called Arg::unnamed() on an Arg::Named!"),
}
}

Expand Down
5 changes: 4 additions & 1 deletion core/codegen/src/derive/from_form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ pub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream {
Ok(quote_spanned! { input.span() =>
/// Rocket generated FormForm context.
#[doc(hidden)]
#[allow(private_in_public)]
#[allow(unknown_lints)]
#[allow(renamed_and_removed_lints)]
#[allow(private_in_public, private_bounds)]
#vis struct #ctxt_ty #impl_gen #where_clause {
__opts: #_form::Options,
__errors: #_form::Errors<'r>,
Expand All @@ -148,6 +150,7 @@ pub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream {
#[allow(unused_imports)]
use #_http::uncased::AsUncased;
})
.outer_mapper(quote!(#[allow(renamed_and_removed_lints)]))
.outer_mapper(quote!(#[allow(private_in_public)]))
.outer_mapper(quote!(#[rocket::async_trait]))
.inner_mapper(MapperBuild::new()
Expand Down
6 changes: 6 additions & 0 deletions core/codegen/src/exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,9 @@ define_exported_paths! {
macro_rules! define_spanned_export {
($span:expr => $($name:ident),*) => ($(define!($span => $name $name);)*)
}

/// Convenience: returns a "mixed site" span located at `span`.
#[inline(always)]
pub fn mixed(span: Span) -> Span {
Span::mixed_site().located_at(span)
}
8 changes: 4 additions & 4 deletions core/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ macro_rules! route_attribute {
///
/// If a request guard fails, the request is forwarded if the
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
/// `Failure`. See [`FromRequest` Outcomes] for further
/// detail.
/// `Error`. See [`FromRequest` Outcomes] for further detail.
///
/// 2. Path and query guards in an unspecified order. If a path
/// or query guard fails, the request is forwarded.
Expand All @@ -249,7 +248,7 @@ macro_rules! route_attribute {
///
/// If a data guard fails, the request is forwarded if the
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
/// `Failure`. See [`FromData`] for further detail.
/// `Error`. See [`FromData`] for further detail.
///
/// If all validation succeeds, the decorated function is called.
/// The returned value is used to generate a [`Response`] via the
Expand Down Expand Up @@ -448,7 +447,7 @@ pub fn main(args: TokenStream, input: TokenStream) -> TokenStream {
/// #[rocket::main]
/// async fn main() {
/// // Recall that an uninspected `Error` will cause a pretty-printed panic,
/// // so rest assured failures do not go undetected when using `#[launch]`.
/// // so rest assured errors do not go undetected when using `#[launch]`.
/// let _ = rocket().launch().await;
/// }
/// ```
Expand Down Expand Up @@ -1457,6 +1456,7 @@ pub fn catchers(input: TokenStream) -> TokenStream {
/// are not ignorable.
///
/// [`Uri`]: ../rocket/http/uri/enum.Uri.html
/// [`Uri::parse_any()`]: ../rocket/http/uri/enum.Uri.html#method.parse_any
/// [`Origin`]: ../rocket/http/uri/struct.Origin.html
/// [`Asterisk`]: ../rocket/http/uri/struct.Asterisk.html
/// [`Authority`]: ../rocket/http/uri/struct.Authority.html
Expand Down
2 changes: 1 addition & 1 deletion core/codegen/tests/from_form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ fn json_wrapper_works() {
assert_eq!(form, JsonToken(Json("foo bar")));
}

// FIXME: https://github.com/rust-lang/rust/issues/86706
#[allow(renamed_and_removed_lints)]
#[allow(private_in_public)]
struct Q<T>(T);

Expand Down
Loading

0 comments on commit 35669cc

Please sign in to comment.