actix_web/web.rs
1//! Essentials helper functions and types for application registration.
2//!
3//! # Request Extractors
4//! - [`Data`]: Application data item
5//! - [`ThinData`]: Cheap-to-clone application data item
6//! - [`ReqData`]: Request-local data item
7//! - [`Path`]: URL path parameters / dynamic segments
8//! - [`Query`]: URL query parameters
9//! - [`Header`]: Typed header
10//! - [`Json`]: JSON payload
11//! - [`Form`]: URL-encoded payload
12//! - [`Bytes`]: Raw payload
13//!
14//! # Responders
15//! - [`Json`]: JSON response
16//! - [`Form`]: URL-encoded response
17//! - [`Bytes`]: Raw bytes response
18//! - [`Redirect`](Redirect::to): Convenient redirect responses
19
20use std::{borrow::Cow, future::Future};
21
22use actix_router::IntoPatterns;
23pub use bytes::{Buf, BufMut, Bytes, BytesMut};
24
25pub use crate::{
26 config::ServiceConfig, data::Data, redirect::Redirect, request_data::ReqData,
27 thin_data::ThinData, types::*,
28};
29use crate::{
30 error::BlockingError, http::Method, service::WebService, FromRequest, Handler, Resource,
31 Responder, Route, Scope,
32};
33
34/// Creates a new resource for a specific path.
35///
36/// Resources may have dynamic path segments. For example, a resource with the path `/a/{name}/c`
37/// would match all incoming requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
38///
39/// A dynamic segment is specified in the form `{identifier}`, where the identifier can be used
40/// later in a request handler to access the matched value for that segment. This is done by looking
41/// up the identifier in the `Path` object returned by [`HttpRequest.match_info()`] method.
42///
43/// By default, each segment matches the regular expression `[^{}/]+`.
44///
45/// You can also specify a custom regex in the form `{identifier:regex}`:
46///
47/// For instance, to route `GET`-requests on any route matching `/users/{userid}/{friend}` and store
48/// `userid` and `friend` in the exposed `Path` object:
49///
50/// # Examples
51/// ```
52/// use actix_web::{web, App, HttpResponse};
53///
54/// let app = App::new().service(
55/// web::resource("/users/{userid}/{friend}")
56/// .route(web::get().to(|| HttpResponse::Ok()))
57/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
58/// );
59/// ```
60pub fn resource<T: IntoPatterns>(path: T) -> Resource {
61 Resource::new(path)
62}
63
64/// Creates scope for common path prefix.
65///
66/// Scopes collect multiple paths under a common path prefix. The scope's path can contain dynamic
67/// path segments.
68///
69/// # Avoid Trailing Slashes
70/// Avoid using trailing slashes in the scope prefix (e.g., `web::scope("/scope/")`). It will almost
71/// certainly not have the expected behavior. See the [documentation on resource definitions][pat]
72/// to understand why this is the case and how to correctly construct scope/prefix definitions.
73///
74/// # Examples
75/// In this example, three routes are set up (and will handle any method):
76/// - `/{project_id}/path1`
77/// - `/{project_id}/path2`
78/// - `/{project_id}/path3`
79///
80/// # Examples
81/// ```
82/// use actix_web::{web, App, HttpResponse};
83///
84/// let app = App::new().service(
85/// web::scope("/{project_id}")
86/// .service(web::resource("/path1").to(|| HttpResponse::Ok()))
87/// .service(web::resource("/path2").to(|| HttpResponse::Ok()))
88/// .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed()))
89/// );
90/// ```
91///
92/// [pat]: crate::dev::ResourceDef#prefix-resources
93pub fn scope(path: &str) -> Scope {
94 Scope::new(path)
95}
96
97/// Creates a new un-configured route.
98pub fn route() -> Route {
99 Route::new()
100}
101
102macro_rules! method_route {
103 ($method_fn:ident, $method_const:ident) => {
104 #[doc = concat!(" Creates a new route with `", stringify!($method_const), "` method guard.")]
105 ///
106 /// # Examples
107 #[doc = concat!(" In this example, one `", stringify!($method_const), " /{project_id}` route is set up:")]
108 /// ```
109 /// use actix_web::{web, App, HttpResponse};
110 ///
111 /// let app = App::new().service(
112 /// web::resource("/{project_id}")
113 #[doc = concat!(" .route(web::", stringify!($method_fn), "().to(|| HttpResponse::Ok()))")]
114 ///
115 /// );
116 /// ```
117 pub fn $method_fn() -> Route {
118 method(Method::$method_const)
119 }
120 };
121}
122
123method_route!(get, GET);
124method_route!(post, POST);
125method_route!(put, PUT);
126method_route!(patch, PATCH);
127method_route!(delete, DELETE);
128method_route!(head, HEAD);
129method_route!(trace, TRACE);
130
131/// Creates a new route with specified method guard.
132///
133/// # Examples
134/// In this example, one `GET /{project_id}` route is set up:
135///
136/// ```
137/// use actix_web::{web, http, App, HttpResponse};
138///
139/// let app = App::new().service(
140/// web::resource("/{project_id}")
141/// .route(web::method(http::Method::GET).to(|| HttpResponse::Ok()))
142/// );
143/// ```
144pub fn method(method: Method) -> Route {
145 Route::new().method(method)
146}
147
148/// Creates a new any-method route with handler.
149///
150/// ```
151/// use actix_web::{web, App, HttpResponse, Responder};
152///
153/// async fn index() -> impl Responder {
154/// HttpResponse::Ok()
155/// }
156///
157/// App::new().service(
158/// web::resource("/").route(
159/// web::to(index))
160/// );
161/// ```
162pub fn to<F, Args>(handler: F) -> Route
163where
164 F: Handler<Args>,
165 Args: FromRequest + 'static,
166 F::Output: Responder + 'static,
167{
168 Route::new().to(handler)
169}
170
171/// Creates a raw service for a specific path.
172///
173/// ```
174/// use actix_web::{dev, web, guard, App, Error, HttpResponse};
175///
176/// async fn my_service(req: dev::ServiceRequest) -> Result<dev::ServiceResponse, Error> {
177/// Ok(req.into_response(HttpResponse::Ok().finish()))
178/// }
179///
180/// let app = App::new().service(
181/// web::service("/users/*")
182/// .guard(guard::Header("content-type", "text/plain"))
183/// .finish(my_service)
184/// );
185/// ```
186pub fn service<T: IntoPatterns>(path: T) -> WebService {
187 WebService::new(path)
188}
189
190/// Create a relative or absolute redirect.
191///
192/// See [`Redirect`] docs for usage details.
193///
194/// # Examples
195/// ```
196/// use actix_web::{web, App};
197///
198/// let app = App::new()
199/// // the client will resolve this redirect to /api/to-path
200/// .service(web::redirect("/api/from-path", "to-path"));
201/// ```
202pub fn redirect(from: impl Into<Cow<'static, str>>, to: impl Into<Cow<'static, str>>) -> Redirect {
203 Redirect::new(from, to)
204}
205
206/// Executes blocking function on a thread pool, returns future that resolves to result of the
207/// function execution.
208pub fn block<F, R>(f: F) -> impl Future<Output = Result<R, BlockingError>>
209where
210 F: FnOnce() -> R + Send + 'static,
211 R: Send + 'static,
212{
213 let fut = actix_rt::task::spawn_blocking(f);
214 async { fut.await.map_err(|_| BlockingError) }
215}