From fc6f974617a606077ab1d99b8ad06b9b75492682 Mon Sep 17 00:00:00 2001 From: Richard Chien Date: Thu, 4 Mar 2021 20:38:47 +0800 Subject: [PATCH] Add "name" attribute to route macro (#1934) --- actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/src/lib.rs | 2 ++ actix-web-codegen/src/route.rs | 19 +++++++++++++++++-- actix-web-codegen/tests/test_macro.rs | 12 ++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index f1dbf8e5f..7c6543d49 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,8 +2,10 @@ ## Unreleased - 2021-xx-xx * Preserve doc comments when using route macros. [#2022] +* Add `name` attribute to `route` macro. [#1934] [#2022]: https://github.com/actix/actix-web/pull/2022 +[#1934]: https://github.com/actix/actix-web/pull/1934 ## 0.5.0-beta.1 - 2021-02-10 diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 670d82ce9..48414d491 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -71,6 +71,7 @@ mod route; /// /// # Attributes /// - `"path"` - Raw literal string with path for which to register handler. +/// - `name="resource_name"` - Specifies resource name for the handler. If not set, the function name of handler is used. /// - `method="HTTP_METHOD"` - Registers HTTP method to provide guard for. Upper-case string, "GET", "POST" for example. /// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard` /// - `wrap="Middleware"` - Registers a resource middleware. @@ -116,6 +117,7 @@ Creates route handler with `actix_web::guard::", stringify!($variant), "`. # Attributes - `"path"` - Raw literal string with path for which to register handler. +- `name="resource_name"` - Specifies resource name for the handler. If not set, the function name of handler is used. - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`. - `wrap="Middleware"` - Registers a resource middleware. diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index e3c5f0368..ac0b7cea1 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -78,6 +78,7 @@ impl TryFrom<&syn::LitStr> for MethodType { struct Args { path: syn::LitStr, + resource_name: Option, guards: Vec, wrappers: Vec, methods: HashSet, @@ -86,6 +87,7 @@ struct Args { impl Args { fn new(args: AttributeArgs, method: Option) -> syn::Result { let mut path = None; + let mut resource_name = None; let mut guards = Vec::new(); let mut wrappers = Vec::new(); let mut methods = HashSet::new(); @@ -109,7 +111,16 @@ impl Args { } }, NestedMeta::Meta(syn::Meta::NameValue(nv)) => { - if nv.path.is_ident("guard") { + if nv.path.is_ident("name") { + if let syn::Lit::Str(lit) = nv.lit { + resource_name = Some(lit); + } else { + return Err(syn::Error::new_spanned( + nv.lit, + "Attribute name expects literal string!", + )); + } + } else if nv.path.is_ident("guard") { if let syn::Lit::Str(lit) = nv.lit { guards.push(Ident::new(&lit.value(), Span::call_site())); } else { @@ -164,6 +175,7 @@ impl Args { } Ok(Args { path: path.unwrap(), + resource_name, guards, wrappers, methods, @@ -276,6 +288,7 @@ impl ToTokens for Route { args: Args { path, + resource_name, guards, wrappers, methods, @@ -283,7 +296,9 @@ impl ToTokens for Route { resource_type, doc_attributes, } = self; - let resource_name = name.to_string(); + let resource_name = resource_name + .as_ref() + .map_or_else(|| name.to_string(), |n| n.value()); let method_guards = { let mut others = methods.iter(); // unwrapping since length is checked to be at least one diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs index 34cdad649..0cbb64ba5 100644 --- a/actix-web-codegen/tests/test_macro.rs +++ b/actix-web-codegen/tests/test_macro.rs @@ -83,6 +83,13 @@ async fn route_test() -> impl Responder { HttpResponse::Ok() } +#[get("/custom_resource_name", name = "custom")] +async fn custom_resource_name_test<'a>(req: actix_web::HttpRequest) -> impl Responder { + assert!(req.url_for_static("custom").is_ok()); + assert!(req.url_for_static("custom_resource_name_test").is_err()); + HttpResponse::Ok() +} + pub struct ChangeStatusCode; impl Transform for ChangeStatusCode @@ -174,6 +181,7 @@ async fn test_body() { .service(patch_test) .service(test_handler) .service(route_test) + .service(custom_resource_name_test) }); let request = srv.request(http::Method::GET, srv.url("/test")); let response = request.send().await.unwrap(); @@ -228,6 +236,10 @@ async fn test_body() { let request = srv.request(http::Method::PATCH, srv.url("/multi")); let response = request.send().await.unwrap(); assert!(!response.status().is_success()); + + let request = srv.request(http::Method::GET, srv.url("/custom_resource_name")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); } #[actix_rt::test]