2019-03-07 11:09:42 -08:00
|
|
|
#![recursion_limit = "512"]
|
2020-06-22 20:09:48 +01:00
|
|
|
|
2019-03-07 11:09:42 -08:00
|
|
|
extern crate proc_macro;
|
|
|
|
|
|
|
|
use proc_macro::TokenStream;
|
|
|
|
|
2020-09-23 05:42:51 +08:00
|
|
|
mod route;
|
2019-03-07 11:09:42 -08:00
|
|
|
|
2020-09-23 05:42:51 +08:00
|
|
|
/// Creates resource handler, allowing multiple HTTP method guards.
|
2019-03-31 10:23:15 +03:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// ## Syntax
|
|
|
|
/// ```text
|
|
|
|
/// #[route("path", method="HTTP_METHOD"[, attributes])]
|
|
|
|
/// ```
|
2019-03-31 10:23:15 +03:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// ### Attributes
|
|
|
|
/// - `"path"` - Raw literal string with path for which to register handler.
|
|
|
|
/// - `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.
|
2019-06-04 10:30:43 -06:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// ### 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`.
|
2019-06-04 10:30:43 -06:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// ## Example
|
2019-06-04 10:30:43 -06:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// ```rust
|
|
|
|
/// use actix_web::HttpResponse;
|
|
|
|
/// use actix_web_codegen::route;
|
2019-06-04 10:30:43 -06:00
|
|
|
///
|
2020-09-23 05:42:51 +08:00
|
|
|
/// #[route("/", method="GET", method="HEAD")]
|
|
|
|
/// async fn example() -> HttpResponse {
|
|
|
|
/// HttpResponse::Ok().finish()
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-06-04 10:30:43 -06:00
|
|
|
#[proc_macro_attribute]
|
2020-09-23 05:42:51 +08:00
|
|
|
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
route::with_method(None, args, input)
|
2019-06-04 10:30:43 -06:00
|
|
|
}
|
|
|
|
|
2020-09-23 05:42:51 +08:00
|
|
|
macro_rules! doc_comment {
|
|
|
|
($x:expr; $($tt:tt)*) => {
|
|
|
|
#[doc = $x]
|
|
|
|
$($tt)*
|
|
|
|
};
|
2019-06-04 10:30:43 -06:00
|
|
|
}
|
|
|
|
|
2020-09-23 05:42:51 +08:00
|
|
|
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()
|
2019-06-04 10:30:43 -06:00
|
|
|
}
|
2020-09-23 05:42:51 +08:00
|
|
|
```
|
|
|
|
"#);
|
|
|
|
#[proc_macro_attribute]
|
|
|
|
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
route::with_method(Some(route::MethodType::$variant), args, input)
|
|
|
|
}
|
|
|
|
})+
|
|
|
|
};
|
2019-06-05 08:43:13 +06:00
|
|
|
}
|
2020-06-22 20:09:48 +01:00
|
|
|
|
2020-09-23 05:42:51 +08:00
|
|
|
method_macro! {
|
|
|
|
Get, get,
|
|
|
|
Post, post,
|
|
|
|
Put, put,
|
|
|
|
Delete, delete,
|
|
|
|
Head, head,
|
|
|
|
Connect, connect,
|
|
|
|
Options, options,
|
|
|
|
Trace, trace,
|
|
|
|
Patch, patch,
|
2020-09-16 23:37:41 +02:00
|
|
|
}
|
|
|
|
|
2020-06-22 20:09:48 +01:00
|
|
|
/// Marks async main function as the actix system entry-point.
|
|
|
|
///
|
|
|
|
/// ## Usage
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// #[actix_web::main]
|
|
|
|
/// async fn main() {
|
|
|
|
/// async { println!("Hello world"); }.await
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[proc_macro_attribute]
|
|
|
|
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
|
|
|
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
|
use quote::quote;
|
|
|
|
|
|
|
|
let mut input = syn::parse_macro_input!(item as syn::ItemFn);
|
|
|
|
let attrs = &input.attrs;
|
|
|
|
let vis = &input.vis;
|
|
|
|
let sig = &mut input.sig;
|
|
|
|
let body = &input.block;
|
|
|
|
let name = &sig.ident;
|
|
|
|
|
|
|
|
if sig.asyncness.is_none() {
|
|
|
|
return syn::Error::new_spanned(sig.fn_token, "only async fn is supported")
|
|
|
|
.to_compile_error()
|
|
|
|
.into();
|
|
|
|
}
|
|
|
|
|
|
|
|
sig.asyncness = None;
|
|
|
|
|
|
|
|
(quote! {
|
|
|
|
#(#attrs)*
|
|
|
|
#vis #sig {
|
|
|
|
actix_web::rt::System::new(stringify!(#name))
|
|
|
|
.block_on(async move { #body })
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.into()
|
|
|
|
}
|