mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 00:21:08 +01:00
Unify route macros (#1705)
This commit is contained in:
parent
f7bcad9567
commit
162121bf8d
@ -1,161 +1,103 @@
|
|||||||
#![recursion_limit = "512"]
|
#![recursion_limit = "512"]
|
||||||
|
|
||||||
//! Helper and convenience macros for Actix-web.
|
|
||||||
//!
|
|
||||||
//! ## Runtime Setup
|
|
||||||
//!
|
|
||||||
//! - [main](attr.main.html)
|
|
||||||
//!
|
|
||||||
//! ## Resource Macros:
|
|
||||||
//!
|
|
||||||
//! - [get](attr.get.html)
|
|
||||||
//! - [post](attr.post.html)
|
|
||||||
//! - [put](attr.put.html)
|
|
||||||
//! - [delete](attr.delete.html)
|
|
||||||
//! - [head](attr.head.html)
|
|
||||||
//! - [connect](attr.connect.html)
|
|
||||||
//! - [options](attr.options.html)
|
|
||||||
//! - [trace](attr.trace.html)
|
|
||||||
//! - [patch](attr.patch.html)
|
|
||||||
//!
|
|
||||||
//! ### Attributes:
|
|
||||||
//!
|
|
||||||
//! - `"path"` - Raw literal string with path for which to register handle. Mandatory.
|
|
||||||
//! - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
|
||||||
//! - `wrap="Middleware"` - Registers a resource middleware.
|
|
||||||
//!
|
|
||||||
//! ### Notes
|
|
||||||
//!
|
|
||||||
//! Function name can be specified as any expression that is going to be accessible to the generate
|
|
||||||
//! code (e.g `my_guard` or `my_module::my_guard`)
|
|
||||||
//!
|
|
||||||
//! ### Example:
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use actix_web::HttpResponse;
|
|
||||||
//! use actix_web_codegen::get;
|
|
||||||
//!
|
|
||||||
//! #[get("/test")]
|
|
||||||
//! async fn async_test() -> Result<HttpResponse, actix_web::Error> {
|
|
||||||
//! Ok(HttpResponse::Ok().finish())
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
mod route;
|
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
/// Creates route handler with `GET` method guard.
|
mod route;
|
||||||
///
|
|
||||||
/// Syntax: `#[get("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// ## Attributes:
|
|
||||||
///
|
|
||||||
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
|
||||||
/// - `guard = "function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
|
||||||
/// - `wrap = "Middleware"` - Registers a resource middleware.
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Get)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `POST` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[post("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html)
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn post(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Post)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `PUT` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[put("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html)
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn put(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Put)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `DELETE` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[delete("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Delete)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `HEAD` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[head("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Head)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `CONNECT` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[connect("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Connect)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `OPTIONS` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[options("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `TRACE` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[trace("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Trace)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates route handler with `PATCH` method guard.
|
|
||||||
///
|
|
||||||
/// Syntax: `#[patch("path" [, attributes])]`
|
|
||||||
///
|
|
||||||
/// Attributes are the same as in [get](attr.get.html).
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn patch(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
route::generate(args, input, route::GuardType::Patch)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates resource handler, allowing multiple HTTP method guards.
|
/// Creates resource handler, allowing multiple HTTP method guards.
|
||||||
///
|
///
|
||||||
/// Syntax: `#[route("path"[, attributes])]`
|
/// ## Syntax
|
||||||
|
/// ```text
|
||||||
|
/// #[route("path", method="HTTP_METHOD"[, attributes])]
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// Example: `#[route("/", method="GET", method="HEAD")]`
|
/// ### Attributes
|
||||||
///
|
/// - `"path"` - Raw literal string with path for which to register handler.
|
||||||
/// ## Attributes
|
/// - `method="HTTP_METHOD"` - Registers HTTP method to provide guard for. Upper-case string, "GET", "POST" for example.
|
||||||
///
|
|
||||||
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
|
||||||
/// - `method="HTTP_METHOD"` - Registers HTTP method to provide guard for.
|
|
||||||
/// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
/// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
||||||
/// - `wrap="Middleware"` - Registers a resource middleware.
|
/// - `wrap="Middleware"` - Registers a resource middleware.
|
||||||
|
///
|
||||||
|
/// ### Notes
|
||||||
|
/// Function name can be specified as any expression that is going to be accessible to the generate
|
||||||
|
/// code, e.g `my_guard` or `my_module::my_guard`.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use actix_web::HttpResponse;
|
||||||
|
/// use actix_web_codegen::route;
|
||||||
|
///
|
||||||
|
/// #[route("/", method="GET", method="HEAD")]
|
||||||
|
/// async fn example() -> HttpResponse {
|
||||||
|
/// HttpResponse::Ok().finish()
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::generate(args, input, route::GuardType::Multi)
|
route::with_method(None, args, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! doc_comment {
|
||||||
|
($x:expr; $($tt:tt)*) => {
|
||||||
|
#[doc = $x]
|
||||||
|
$($tt)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! method_macro {
|
||||||
|
(
|
||||||
|
$($variant:ident, $method:ident,)+
|
||||||
|
) => {
|
||||||
|
$(doc_comment! {
|
||||||
|
concat!("
|
||||||
|
Creates route handler with `actix_web::guard::", stringify!($variant), "`.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
```text
|
||||||
|
#[", stringify!($method), r#"("path"[, attributes])]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
- `"path"` - Raw literal string with path for which to register handler.
|
||||||
|
- `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`.
|
||||||
|
- `wrap="Middleware"` - Registers a resource middleware.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
Function name can be specified as any expression that is going to be accessible to the generate
|
||||||
|
code, e.g `my_guard` or `my_module::my_guard`.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use actix_web::HttpResponse;
|
||||||
|
use actix_web_codegen::"#, stringify!($method), ";
|
||||||
|
|
||||||
|
#[", stringify!($method), r#"("/")]
|
||||||
|
async fn example() -> HttpResponse {
|
||||||
|
HttpResponse::Ok().finish()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"#);
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
route::with_method(Some(route::MethodType::$variant), args, input)
|
||||||
|
}
|
||||||
|
})+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
method_macro! {
|
||||||
|
Get, get,
|
||||||
|
Post, post,
|
||||||
|
Put, put,
|
||||||
|
Delete, delete,
|
||||||
|
Head, head,
|
||||||
|
Connect, connect,
|
||||||
|
Options, options,
|
||||||
|
Trace, trace,
|
||||||
|
Patch, patch,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marks async main function as the actix system entry-point.
|
/// Marks async main function as the actix system entry-point.
|
||||||
|
@ -20,63 +20,59 @@ impl ToTokens for ResourceType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! method_type {
|
||||||
|
(
|
||||||
|
$($variant:ident, $upper:ident,)+
|
||||||
|
) => {
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum GuardType {
|
pub enum MethodType {
|
||||||
Get,
|
$(
|
||||||
Post,
|
$variant,
|
||||||
Put,
|
)+
|
||||||
Delete,
|
|
||||||
Head,
|
|
||||||
Connect,
|
|
||||||
Options,
|
|
||||||
Trace,
|
|
||||||
Patch,
|
|
||||||
Multi,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuardType {
|
impl MethodType {
|
||||||
fn as_str(&self) -> &'static str {
|
fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
GuardType::Get => "Get",
|
$(Self::$variant => stringify!($variant),)+
|
||||||
GuardType::Post => "Post",
|
|
||||||
GuardType::Put => "Put",
|
|
||||||
GuardType::Delete => "Delete",
|
|
||||||
GuardType::Head => "Head",
|
|
||||||
GuardType::Connect => "Connect",
|
|
||||||
GuardType::Options => "Options",
|
|
||||||
GuardType::Trace => "Trace",
|
|
||||||
GuardType::Patch => "Patch",
|
|
||||||
GuardType::Multi => "Multi",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for GuardType {
|
fn parse(method: &str) -> Result<Self, String> {
|
||||||
|
match method {
|
||||||
|
$(stringify!($upper) => Ok(Self::$variant),)+
|
||||||
|
_ => Err(format!("Unexpected HTTP method: `{}`", method)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
method_type! {
|
||||||
|
Get, GET,
|
||||||
|
Post, POST,
|
||||||
|
Put, PUT,
|
||||||
|
Delete, DELETE,
|
||||||
|
Head, HEAD,
|
||||||
|
Connect, CONNECT,
|
||||||
|
Options, OPTIONS,
|
||||||
|
Trace, TRACE,
|
||||||
|
Patch, PATCH,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for MethodType {
|
||||||
fn to_tokens(&self, stream: &mut TokenStream2) {
|
fn to_tokens(&self, stream: &mut TokenStream2) {
|
||||||
let ident = Ident::new(self.as_str(), Span::call_site());
|
let ident = Ident::new(self.as_str(), Span::call_site());
|
||||||
stream.append(ident);
|
stream.append(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&syn::LitStr> for GuardType {
|
impl TryFrom<&syn::LitStr> for MethodType {
|
||||||
type Error = syn::Error;
|
type Error = syn::Error;
|
||||||
|
|
||||||
fn try_from(value: &syn::LitStr) -> Result<Self, Self::Error> {
|
fn try_from(value: &syn::LitStr) -> Result<Self, Self::Error> {
|
||||||
match value.value().as_str() {
|
Self::parse(value.value().as_str())
|
||||||
"CONNECT" => Ok(GuardType::Connect),
|
.map_err(|message| syn::Error::new_spanned(value, message))
|
||||||
"DELETE" => Ok(GuardType::Delete),
|
|
||||||
"GET" => Ok(GuardType::Get),
|
|
||||||
"HEAD" => Ok(GuardType::Head),
|
|
||||||
"OPTIONS" => Ok(GuardType::Options),
|
|
||||||
"PATCH" => Ok(GuardType::Patch),
|
|
||||||
"POST" => Ok(GuardType::Post),
|
|
||||||
"PUT" => Ok(GuardType::Put),
|
|
||||||
"TRACE" => Ok(GuardType::Trace),
|
|
||||||
_ => Err(syn::Error::new_spanned(
|
|
||||||
value,
|
|
||||||
&format!("Unexpected HTTP Method: `{}`", value.value()),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,15 +80,21 @@ struct Args {
|
|||||||
path: syn::LitStr,
|
path: syn::LitStr,
|
||||||
guards: Vec<Ident>,
|
guards: Vec<Ident>,
|
||||||
wrappers: Vec<syn::Type>,
|
wrappers: Vec<syn::Type>,
|
||||||
methods: HashSet<GuardType>,
|
methods: HashSet<MethodType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
fn new(args: AttributeArgs) -> syn::Result<Self> {
|
fn new(args: AttributeArgs, method: Option<MethodType>) -> syn::Result<Self> {
|
||||||
let mut path = None;
|
let mut path = None;
|
||||||
let mut guards = Vec::new();
|
let mut guards = Vec::new();
|
||||||
let mut wrappers = Vec::new();
|
let mut wrappers = Vec::new();
|
||||||
let mut methods = HashSet::new();
|
let mut methods = HashSet::new();
|
||||||
|
|
||||||
|
let is_route_macro = method.is_none();
|
||||||
|
if let Some(method) = method {
|
||||||
|
methods.insert(method);
|
||||||
|
}
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
|
NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
|
||||||
@ -126,13 +128,18 @@ impl Args {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if nv.path.is_ident("method") {
|
} else if nv.path.is_ident("method") {
|
||||||
if let syn::Lit::Str(ref lit) = nv.lit {
|
if !is_route_macro {
|
||||||
let guard = GuardType::try_from(lit)?;
|
return Err(syn::Error::new_spanned(
|
||||||
if !methods.insert(guard) {
|
&nv,
|
||||||
|
"HTTP method forbidden here. To handle multiple methods, use `route` instead",
|
||||||
|
));
|
||||||
|
} else if let syn::Lit::Str(ref lit) = nv.lit {
|
||||||
|
let method = MethodType::try_from(lit)?;
|
||||||
|
if !methods.insert(method) {
|
||||||
return Err(syn::Error::new_spanned(
|
return Err(syn::Error::new_spanned(
|
||||||
&nv.lit,
|
&nv.lit,
|
||||||
&format!(
|
&format!(
|
||||||
"HTTP Method defined more than once: `{}`",
|
"HTTP method defined more than once: `{}`",
|
||||||
lit.value()
|
lit.value()
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -169,7 +176,6 @@ pub struct Route {
|
|||||||
args: Args,
|
args: Args,
|
||||||
ast: syn::ItemFn,
|
ast: syn::ItemFn,
|
||||||
resource_type: ResourceType,
|
resource_type: ResourceType,
|
||||||
guard: GuardType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guess_resource_type(typ: &syn::Type) -> ResourceType {
|
fn guess_resource_type(typ: &syn::Type) -> ResourceType {
|
||||||
@ -198,23 +204,25 @@ impl Route {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
args: AttributeArgs,
|
args: AttributeArgs,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
guard: GuardType,
|
method: Option<MethodType>,
|
||||||
) -> syn::Result<Self> {
|
) -> syn::Result<Self> {
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!(
|
format!(
|
||||||
r#"invalid server definition, expected #[{}("<some path>")]"#,
|
r#"invalid service definition, expected #[{}("<some path>")]"#,
|
||||||
guard.as_str().to_ascii_lowercase()
|
method
|
||||||
|
.map(|it| it.as_str())
|
||||||
|
.unwrap_or("route")
|
||||||
|
.to_ascii_lowercase()
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let ast: syn::ItemFn = syn::parse(input)?;
|
let ast: syn::ItemFn = syn::parse(input)?;
|
||||||
let name = ast.sig.ident.clone();
|
let name = ast.sig.ident.clone();
|
||||||
|
|
||||||
let args = Args::new(args)?;
|
let args = Args::new(args, method)?;
|
||||||
|
if args.methods.is_empty() {
|
||||||
if guard == GuardType::Multi && args.methods.is_empty() {
|
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
"The #[route(..)] macro requires at least one `method` attribute",
|
"The #[route(..)] macro requires at least one `method` attribute",
|
||||||
@ -240,7 +248,6 @@ impl Route {
|
|||||||
args,
|
args,
|
||||||
ast,
|
ast,
|
||||||
resource_type,
|
resource_type,
|
||||||
guard,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +256,6 @@ impl ToTokens for Route {
|
|||||||
fn to_tokens(&self, output: &mut TokenStream2) {
|
fn to_tokens(&self, output: &mut TokenStream2) {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
guard,
|
|
||||||
ast,
|
ast,
|
||||||
args:
|
args:
|
||||||
Args {
|
Args {
|
||||||
@ -261,21 +267,22 @@ impl ToTokens for Route {
|
|||||||
resource_type,
|
resource_type,
|
||||||
} = self;
|
} = self;
|
||||||
let resource_name = name.to_string();
|
let resource_name = name.to_string();
|
||||||
let mut methods = methods.iter();
|
let method_guards = {
|
||||||
|
let mut others = methods.iter();
|
||||||
let method_guards = if *guard == GuardType::Multi {
|
|
||||||
// unwrapping since length is checked to be at least one
|
// unwrapping since length is checked to be at least one
|
||||||
let first = methods.next().unwrap();
|
let first = others.next().unwrap();
|
||||||
|
|
||||||
|
if methods.len() > 1 {
|
||||||
quote! {
|
quote! {
|
||||||
.guard(
|
.guard(
|
||||||
actix_web::guard::Any(actix_web::guard::#first())
|
actix_web::guard::Any(actix_web::guard::#first())
|
||||||
#(.or(actix_web::guard::#methods()))*
|
#(.or(actix_web::guard::#others()))*
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
.guard(actix_web::guard::#guard())
|
.guard(actix_web::guard::#first())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -302,13 +309,13 @@ impl ToTokens for Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generate(
|
pub(crate) fn with_method(
|
||||||
|
method: Option<MethodType>,
|
||||||
args: TokenStream,
|
args: TokenStream,
|
||||||
input: TokenStream,
|
input: TokenStream,
|
||||||
guard: GuardType,
|
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let args = parse_macro_input!(args as syn::AttributeArgs);
|
let args = parse_macro_input!(args as syn::AttributeArgs);
|
||||||
match Route::new(args, input, guard) {
|
match Route::new(args, input, method) {
|
||||||
Ok(route) => route.into_token_stream().into(),
|
Ok(route) => route.into_token_stream().into(),
|
||||||
Err(err) => err.to_compile_error().into(),
|
Err(err) => err.to_compile_error().into(),
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: HTTP Method defined more than once: `GET`
|
error: HTTP method defined more than once: `GET`
|
||||||
--> $DIR/route-duplicate-method-fail.rs:3:35
|
--> $DIR/route-duplicate-method-fail.rs:3:35
|
||||||
|
|
|
|
||||||
3 | #[route("/", method="GET", method="GET")]
|
3 | #[route("/", method="GET", method="GET")]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: Unexpected HTTP Method: `UNEXPECTED`
|
error: Unexpected HTTP method: `UNEXPECTED`
|
||||||
--> $DIR/route-unexpected-method-fail.rs:3:21
|
--> $DIR/route-unexpected-method-fail.rs:3:21
|
||||||
|
|
|
|
||||||
3 | #[route("/", method="UNEXPECTED")]
|
3 | #[route("/", method="UNEXPECTED")]
|
||||||
|
@ -22,4 +22,9 @@ async fn four() -> impl Responder {
|
|||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[delete("/five", method="GET")]
|
||||||
|
async fn five() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -21,3 +21,9 @@ error: Multiple paths specified! Should be only one!
|
|||||||
|
|
|
|
||||||
20 | #[delete("/four", "/five")]
|
20 | #[delete("/four", "/five")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: HTTP method forbidden here. To handle multiple methods, use `route` instead
|
||||||
|
--> $DIR/simple-fail.rs:25:19
|
||||||
|
|
|
||||||
|
25 | #[delete("/five", method="GET")]
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
Loading…
Reference in New Issue
Block a user