Skip to main content

actix_web_codegen/
lib.rs

1//! Routing and runtime macros for Actix Web.
2//!
3//! # Actix Web Re-exports
4//! Actix Web re-exports a version of this crate in it's entirety so you usually don't have to
5//! specify a dependency on this crate explicitly. Sometimes, however, updates are made to this
6//! crate before the actix-web dependency is updated. Therefore, code examples here will show
7//! explicit imports. Check the latest [actix-web attributes docs] to see which macros
8//! are re-exported.
9//!
10//! # Runtime Setup
11//! Used for setting up the actix async runtime. See [macro@main] macro docs.
12//!
13//! ```
14//! #[actix_web_codegen::main] // or `#[actix_web::main]` in Actix Web apps
15//! async fn main() {
16//!     async { println!("Hello world"); }.await
17//! }
18//! ```
19//!
20//! # Single Method Handler
21//! There is a macro to set up a handler for each of the most common HTTP methods that also define
22//! additional guards and route-specific middleware.
23//!
24//! See docs for: [GET], [POST], [PATCH], [PUT], [DELETE], [HEAD], [CONNECT], [OPTIONS], [TRACE]
25//!
26//! ```
27//! # use actix_web::HttpResponse;
28//! # use actix_web_codegen::get;
29//! #[get("/test")]
30//! async fn get_handler() -> HttpResponse {
31//!     HttpResponse::Ok().finish()
32//! }
33//! ```
34//!
35//! # Multiple Method Handlers
36//! Similar to the single method handler macro but takes one or more arguments for the HTTP methods
37//! it should respond to. See [macro@route] macro docs.
38//!
39//! ```
40//! # use actix_web::HttpResponse;
41//! # use actix_web_codegen::route;
42//! #[route("/test", method = "GET", method = "HEAD")]
43//! async fn get_and_head_handler() -> HttpResponse {
44//!     HttpResponse::Ok().finish()
45//! }
46//! ```
47//!
48//! # Multiple Path Handlers
49//! Acts as a wrapper for multiple single method handler macros. It takes no arguments and
50//! delegates those to the macros for the individual methods. See [macro@routes] macro docs.
51//!
52//! ```
53//! # use actix_web::HttpResponse;
54//! # use actix_web_codegen::routes;
55//! #[routes]
56//! #[get("/test")]
57//! #[get("/test2")]
58//! #[delete("/test")]
59//! async fn example() -> HttpResponse {
60//!     HttpResponse::Ok().finish()
61//! }
62//! ```
63//!
64//! [actix-web attributes docs]: https://docs.rs/actix-web/latest/actix_web/#attributes
65//! [GET]: macro@get
66//! [POST]: macro@post
67//! [PUT]: macro@put
68//! [HEAD]: macro@head
69//! [CONNECT]: macro@macro@connect
70//! [OPTIONS]: macro@options
71//! [TRACE]: macro@trace
72//! [PATCH]: macro@patch
73//! [DELETE]: macro@delete
74
75#![recursion_limit = "512"]
76#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
77#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
78#![cfg_attr(docsrs, feature(doc_cfg))]
79
80use proc_macro::TokenStream;
81use quote::quote;
82
83mod route;
84mod scope;
85
86/// Creates resource handler, allowing multiple HTTP method guards.
87///
88/// # Syntax
89/// ```plain
90/// #[route("path", method="HTTP_METHOD"[, attributes])]
91/// ```
92///
93/// # Attributes
94/// - `"path"`: Raw literal string with path for which to register handler.
95/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function
96///   name of handler is used.
97/// - `method = "HTTP_METHOD"`: Registers HTTP method to provide guard for. Upper-case string,
98///   "GET", "POST" for example.
99/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
100/// - `wrap = "Middleware"`: Registers a resource middleware.
101///
102/// # Notes
103/// Function name can be specified as any expression that is going to be accessible to the generate
104/// code, e.g `my_guard` or `my_module::my_guard`.
105///
106/// # Examples
107/// ```
108/// # use actix_web::HttpResponse;
109/// # use actix_web_codegen::route;
110/// #[route("/test", method = "GET", method = "HEAD", method = "CUSTOM")]
111/// async fn example() -> HttpResponse {
112///     HttpResponse::Ok().finish()
113/// }
114/// ```
115#[proc_macro_attribute]
116pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
117    route::with_method(None, args, input)
118}
119
120/// Creates resource handler, allowing multiple HTTP methods and paths.
121///
122/// # Syntax
123/// ```plain
124/// #[routes]
125/// #[<method>("path", ...)]
126/// #[<method>("path", ...)]
127/// ...
128/// ```
129///
130/// # Attributes
131/// The `routes` macro itself has no parameters, but allows specifying the attribute macros for
132/// the multiple paths and/or methods, e.g. [`GET`](macro@get) and [`POST`](macro@post).
133///
134/// These helper attributes take the same parameters as the [single method handlers](crate#single-method-handler).
135///
136/// # Examples
137/// ```
138/// # use actix_web::HttpResponse;
139/// # use actix_web_codegen::routes;
140/// #[routes]
141/// #[get("/test")]
142/// #[get("/test2")]
143/// #[delete("/test")]
144/// async fn example() -> HttpResponse {
145///     HttpResponse::Ok().finish()
146/// }
147/// ```
148#[proc_macro_attribute]
149pub fn routes(_: TokenStream, input: TokenStream) -> TokenStream {
150    route::with_methods(input)
151}
152
153macro_rules! method_macro {
154    ($variant:ident, $method:ident) => {
155        #[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")]
156        ///
157        /// # Syntax
158        /// ```plain
159        #[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)]
160        /// ```
161        ///
162        /// # Attributes
163        /// - `"path"`: Raw literal string with path for which to register handler.
164        /// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the
165        ///   function name of handler is used.
166        /// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
167        /// - `wrap = "Middleware"`: Registers a resource middleware.
168        ///
169        /// # Notes
170        /// Function name can be specified as any expression that is going to be accessible to the
171        /// generate code, e.g `my_guard` or `my_module::my_guard`.
172        ///
173        /// # Examples
174        /// ```
175        /// # use actix_web::HttpResponse;
176        #[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")]
177        #[doc = concat!("#[", stringify!($method), r#"("/")]"#)]
178        /// async fn example() -> HttpResponse {
179        ///     HttpResponse::Ok().finish()
180        /// }
181        /// ```
182        #[proc_macro_attribute]
183        pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
184            route::with_method(Some(route::MethodType::$variant), args, input)
185        }
186    };
187}
188
189method_macro!(Get, get);
190method_macro!(Post, post);
191method_macro!(Put, put);
192method_macro!(Delete, delete);
193method_macro!(Head, head);
194method_macro!(Connect, connect);
195method_macro!(Options, options);
196method_macro!(Trace, trace);
197method_macro!(Patch, patch);
198
199/// Prepends a path prefix to all handlers using routing macros inside the attached module.
200///
201/// # Syntax
202///
203/// ```
204/// # use actix_web_codegen::scope;
205/// #[scope("/prefix")]
206/// mod api {
207///     // ...
208/// }
209/// ```
210///
211/// # Arguments
212///
213/// - `"/prefix"` - Raw literal string to be prefixed onto contained handlers' paths.
214///
215/// # Example
216///
217/// ```
218/// # use actix_web_codegen::{scope, get};
219/// # use actix_web::Responder;
220/// #[scope("/api")]
221/// mod api {
222///     # use super::*;
223///     #[get("/hello")]
224///     pub async fn hello() -> impl Responder {
225///         // this has path /api/hello
226///         "Hello, world!"
227///     }
228/// }
229/// # fn main() {}
230/// ```
231#[proc_macro_attribute]
232pub fn scope(args: TokenStream, input: TokenStream) -> TokenStream {
233    scope::with_scope(args, input)
234}
235
236/// Marks async main function as the Actix Web system entry-point.
237///
238/// Note that Actix Web also works under `#[tokio::main]` since version 4.0. However, this macro is
239/// still necessary for actor support (since actors use a `System`). Read more in the
240/// [`actix_web::rt`](https://docs.rs/actix-web/4/actix_web/rt) module docs.
241///
242/// # Examples
243/// ```
244/// #[actix_web::main]
245/// async fn main() {
246///     async { println!("Hello world"); }.await
247/// }
248/// ```
249#[proc_macro_attribute]
250pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
251    let mut output: TokenStream = (quote! {
252        #[::actix_web::rt::main(system = "::actix_web::rt::System")]
253    })
254    .into();
255
256    output.extend(item);
257    output
258}
259
260/// Marks async test functions to use the Actix Web system entry-point.
261///
262/// # Examples
263/// ```
264/// #[actix_web::test]
265/// async fn test() {
266///     assert_eq!(async { "Hello world" }.await, "Hello world");
267/// }
268/// ```
269#[proc_macro_attribute]
270pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
271    let mut output: TokenStream = (quote! {
272        #[::actix_web::rt::test(system = "::actix_web::rt::System")]
273    })
274    .into();
275
276    output.extend(item);
277    output
278}
279
280/// Converts the error to a token stream and appends it to the original input.
281///
282/// Returning the original input in addition to the error is good for IDEs which can gracefully
283/// recover and show more precise errors within the macro body.
284///
285/// See <https://github.com/rust-analyzer/rust-analyzer/issues/10468> for more info.
286fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream {
287    let compile_err = TokenStream::from(err.to_compile_error());
288    item.extend(compile_err);
289    item
290}