mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 00:21:08 +01:00
refactor web module (#2379)
This commit is contained in:
parent
53ec66caf4
commit
d8a0f46f26
@ -6,4 +6,4 @@ ci-min-test = "hack check --workspace --no-default-features --tests --examples"
|
|||||||
ci-default = "check --workspace --bins --tests --examples"
|
ci-default = "check --workspace --bins --tests --examples"
|
||||||
ci-full = "check --workspace --all-features --bins --tests --examples"
|
ci-full = "check --workspace --all-features --bins --tests --examples"
|
||||||
ci-test = "test --workspace --all-features --lib --tests --no-fail-fast -- --nocapture"
|
ci-test = "test --workspace --all-features --lib --tests --no-fail-fast -- --nocapture"
|
||||||
ci-doctest = "hack test --workspace --all-features --doc --no-fail-fast -- --nocapture"
|
ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture"
|
||||||
|
40
.github/workflows/ci.yml
vendored
40
.github/workflows/ci.yml
vendored
@ -80,13 +80,6 @@ jobs:
|
|||||||
command: ci-test
|
command: ci-test
|
||||||
args: --skip=test_reading_deflate_encoding_large_random_rustls
|
args: --skip=test_reading_deflate_encoding_large_random_rustls
|
||||||
|
|
||||||
- name: doc tests
|
|
||||||
# due to unknown issue with running doc tests on macOS
|
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
timeout-minutes: 40
|
|
||||||
with: { command: ci-doctest }
|
|
||||||
|
|
||||||
- name: Generate coverage file
|
- name: Generate coverage file
|
||||||
if: >
|
if: >
|
||||||
matrix.target.os == 'ubuntu-latest'
|
matrix.target.os == 'ubuntu-latest'
|
||||||
@ -106,5 +99,36 @@ jobs:
|
|||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
cargo install cargo-cache --version 0.6.3 --no-default-features --features ci-autoclean
|
||||||
cargo-cache
|
cargo-cache
|
||||||
|
|
||||||
|
rustdoc:
|
||||||
|
name: rustdoc
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Rust (nightly)
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: nightly-x86_64-unknown-linux-gnu
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Generate Cargo.lock
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with: { command: generate-lockfile }
|
||||||
|
- name: Cache Dependencies
|
||||||
|
uses: Swatinem/rust-cache@v1.3.0
|
||||||
|
|
||||||
|
- name: Install cargo-hack
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: install
|
||||||
|
args: cargo-hack
|
||||||
|
|
||||||
|
- name: doc tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
timeout-minutes: 40
|
||||||
|
with: { command: ci-doctest }
|
||||||
|
@ -5,14 +5,17 @@
|
|||||||
* Re-export actix-service `ServiceFactory` in `dev` module. [#2325]
|
* Re-export actix-service `ServiceFactory` in `dev` module. [#2325]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Minimum supported Rust version (MSRV) is now 1.51.
|
|
||||||
* Compress middleware will return 406 Not Acceptable when no content encoding is acceptable to the client. [#2344]
|
* Compress middleware will return 406 Not Acceptable when no content encoding is acceptable to the client. [#2344]
|
||||||
|
* Move `BaseHttpResponse` to `dev::Response`. [#2379]
|
||||||
|
* Minimum supported Rust version (MSRV) is now 1.51.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fix quality parse error in Accept-Encoding header. [#2344]
|
* Fix quality parse error in Accept-Encoding header. [#2344]
|
||||||
|
* Re-export correct type at `web::HttpResponse`. [#2379]
|
||||||
|
|
||||||
[#2325]: https://github.com/actix/actix-web/pull/2325
|
[#2325]: https://github.com/actix/actix-web/pull/2325
|
||||||
[#2344]: https://github.com/actix/actix-web/pull/2344
|
[#2344]: https://github.com/actix/actix-web/pull/2344
|
||||||
|
[#2379]: https://github.com/actix/actix-web/pull/2379
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.8 - 2021-06-26
|
## 4.0.0-beta.8 - 2021-06-26
|
||||||
|
@ -18,7 +18,7 @@ pub use actix_http::body::{AnyBody, Body, BodySize, MessageBody, ResponseBody, S
|
|||||||
|
|
||||||
#[cfg(feature = "__compress")]
|
#[cfg(feature = "__compress")]
|
||||||
pub use actix_http::encoding::Decoder as Decompress;
|
pub use actix_http::encoding::Decoder as Decompress;
|
||||||
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, ResponseHead};
|
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, Response, ResponseHead};
|
||||||
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
||||||
pub use actix_server::Server;
|
pub use actix_server::Server;
|
||||||
pub use actix_service::{
|
pub use actix_service::{
|
||||||
@ -26,7 +26,7 @@ pub use actix_service::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::http::header::ContentEncoding;
|
use crate::http::header::ContentEncoding;
|
||||||
use actix_http::{Response, ResponseBuilder};
|
use actix_http::ResponseBuilder;
|
||||||
|
|
||||||
use actix_router::Patterns;
|
use actix_router::Patterns;
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
//! # References
|
//! # References
|
||||||
//!
|
//!
|
||||||
//! "The Content-Disposition Header Field" https://www.ietf.org/rfc/rfc2183.txt
|
//! "The Content-Disposition Header Field" <https://www.ietf.org/rfc/rfc2183.txt>
|
||||||
//! "The Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)" https://www.ietf.org/rfc/rfc6266.txt
|
//! "The Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)" <https://www.ietf.org/rfc/rfc6266.txt>
|
||||||
//! "Returning Values from Forms: multipart/form-data" https://www.ietf.org/rfc/rfc7578.txt
|
//! "Returning Values from Forms: multipart/form-data" <https://www.ietf.org/rfc/rfc7578.txt>
|
||||||
//! Browser conformance tests at: http://greenbytes.de/tech/tc2231/
|
//! Browser conformance tests at: <http://greenbytes.de/tech/tc2231/>
|
||||||
//! IANA assignment: http://www.iana.org/assignments/cont-disp/cont-disp.xhtml
|
//! IANA assignment: <http://www.iana.org/assignments/cont-disp/cont-disp.xhtml>
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -96,7 +96,6 @@ pub mod test;
|
|||||||
pub(crate) mod types;
|
pub(crate) mod types;
|
||||||
pub mod web;
|
pub mod web;
|
||||||
|
|
||||||
pub use actix_http::Response as BaseHttpResponse;
|
|
||||||
pub use actix_http::{body, HttpMessage};
|
pub use actix_http::{body, HttpMessage};
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use actix_rt as rt;
|
pub use actix_rt as rt;
|
||||||
|
@ -476,7 +476,7 @@ impl WebService {
|
|||||||
|
|
||||||
/// Set service name.
|
/// Set service name.
|
||||||
///
|
///
|
||||||
/// Name is used for url generation.
|
/// Name is used for URL generation.
|
||||||
pub fn name(mut self, name: &str) -> Self {
|
pub fn name(mut self, name: &str) -> Self {
|
||||||
self.name = Some(name.to_string());
|
self.name = Some(name.to_string());
|
||||||
self
|
self
|
||||||
|
220
src/web.rs
220
src/web.rs
@ -3,44 +3,36 @@
|
|||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
use actix_http::http::Method;
|
use actix_http::http::Method;
|
||||||
pub use actix_http::Response as HttpResponse;
|
|
||||||
use actix_router::IntoPatterns;
|
use actix_router::IntoPatterns;
|
||||||
pub use bytes::{Buf, BufMut, Bytes, BytesMut};
|
pub use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
|
||||||
use crate::error::BlockingError;
|
use crate::{
|
||||||
use crate::extract::FromRequest;
|
error::BlockingError, extract::FromRequest, handler::Handler, resource::Resource,
|
||||||
use crate::handler::Handler;
|
responder::Responder, route::Route, scope::Scope, service::WebService,
|
||||||
use crate::resource::Resource;
|
};
|
||||||
use crate::responder::Responder;
|
|
||||||
use crate::route::Route;
|
|
||||||
use crate::scope::Scope;
|
|
||||||
use crate::service::WebService;
|
|
||||||
|
|
||||||
pub use crate::config::ServiceConfig;
|
pub use crate::config::ServiceConfig;
|
||||||
pub use crate::data::Data;
|
pub use crate::data::Data;
|
||||||
pub use crate::request::HttpRequest;
|
pub use crate::request::HttpRequest;
|
||||||
pub use crate::request_data::ReqData;
|
pub use crate::request_data::ReqData;
|
||||||
|
pub use crate::response::HttpResponse;
|
||||||
pub use crate::types::*;
|
pub use crate::types::*;
|
||||||
|
|
||||||
/// Create resource for a specific path.
|
/// Creates a new resource for a specific path.
|
||||||
///
|
///
|
||||||
/// Resources may have variable path segments. For example, a
|
/// Resources may have dynamic path segments. For example, a resource with the path `/a/{name}/c`
|
||||||
/// resource with the path `/a/{name}/c` would match all incoming
|
/// would match all incoming requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
|
||||||
/// requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
|
|
||||||
///
|
///
|
||||||
/// A variable segment is specified in the form `{identifier}`,
|
/// A dynamic segment is specified in the form `{identifier}`, where the identifier can be used
|
||||||
/// where the identifier can be used later in a request handler to
|
/// later in a request handler to access the matched value for that segment. This is done by looking
|
||||||
/// access the matched value for that segment. This is done by
|
/// up the identifier in the `Path` object returned by [`HttpRequest.match_info()`] method.
|
||||||
/// looking up the identifier in the `Params` object returned by
|
|
||||||
/// `HttpRequest.match_info()` method.
|
|
||||||
///
|
///
|
||||||
/// By default, each segment matches the regular expression `[^{}/]+`.
|
/// By default, each segment matches the regular expression `[^{}/]+`.
|
||||||
///
|
///
|
||||||
/// You can also specify a custom regex in the form `{identifier:regex}`:
|
/// You can also specify a custom regex in the form `{identifier:regex}`:
|
||||||
///
|
///
|
||||||
/// For instance, to route `GET`-requests on any route matching
|
/// For instance, to route `GET`-requests on any route matching `/users/{userid}/{friend}` and store
|
||||||
/// `/users/{userid}/{friend}` and store `userid` and `friend` in
|
/// `userid` and `friend` in the exposed `Path` object:
|
||||||
/// the exposed `Params` object:
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
/// use actix_web::{web, App, HttpResponse};
|
||||||
@ -55,10 +47,16 @@ pub fn resource<T: IntoPatterns>(path: T) -> Resource {
|
|||||||
Resource::new(path)
|
Resource::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure scope for common root path.
|
/// Creates scope for common path prefix.
|
||||||
///
|
///
|
||||||
/// Scopes collect multiple paths under a common path prefix.
|
/// Scopes collect multiple paths under a common path prefix. The scope's path can contain dynamic
|
||||||
/// Scope path can contain variable path segments as resources.
|
/// path segments.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// In this example, three routes are set up (and will handle any method):
|
||||||
|
/// * `/{project_id}/path1`
|
||||||
|
/// * `/{project_id}/path2`
|
||||||
|
/// * `/{project_id}/path3`
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
/// use actix_web::{web, App, HttpResponse};
|
||||||
@ -70,148 +68,50 @@ pub fn resource<T: IntoPatterns>(path: T) -> Resource {
|
|||||||
/// .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed()))
|
/// .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed()))
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
/// In the above example, three routes get added:
|
|
||||||
/// * /{project_id}/path1
|
|
||||||
/// * /{project_id}/path2
|
|
||||||
/// * /{project_id}/path3
|
|
||||||
///
|
|
||||||
pub fn scope(path: &str) -> Scope {
|
pub fn scope(path: &str) -> Scope {
|
||||||
Scope::new(path)
|
Scope::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create *route* without configuration.
|
/// Creates a new un-configured route.
|
||||||
pub fn route() -> Route {
|
pub fn route() -> Route {
|
||||||
Route::new()
|
Route::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create *route* with `GET` method guard.
|
macro_rules! method_route {
|
||||||
///
|
($method_fn:ident, $method_const:ident) => {
|
||||||
/// ```
|
paste::paste! {
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
#[doc = "Creates a new route with `" $method_const "` method guard."]
|
||||||
///
|
///
|
||||||
/// let app = App::new().service(
|
/// # Examples
|
||||||
/// web::resource("/{project_id}")
|
#[doc = "In this example, one `" $method_const " /{project_id}` route is set up:"]
|
||||||
/// .route(web::get().to(|| HttpResponse::Ok()))
|
/// ```
|
||||||
/// );
|
/// use actix_web::{web, App, HttpResponse};
|
||||||
/// ```
|
///
|
||||||
///
|
/// let app = App::new().service(
|
||||||
/// In the above example, one `GET` route gets added:
|
/// web::resource("/{project_id}")
|
||||||
/// * /{project_id}
|
#[doc = " .route(web::" $method_fn "().to(|| HttpResponse::Ok()))"]
|
||||||
///
|
///
|
||||||
pub fn get() -> Route {
|
/// );
|
||||||
method(Method::GET)
|
/// ```
|
||||||
|
pub fn $method_fn() -> Route {
|
||||||
|
method(Method::$method_const)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create *route* with `POST` method guard.
|
method_route!(get, GET);
|
||||||
///
|
method_route!(post, POST);
|
||||||
/// ```
|
method_route!(put, PUT);
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
method_route!(patch, PATCH);
|
||||||
///
|
method_route!(delete, DELETE);
|
||||||
/// let app = App::new().service(
|
method_route!(head, HEAD);
|
||||||
/// web::resource("/{project_id}")
|
method_route!(trace, TRACE);
|
||||||
/// .route(web::post().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `POST` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn post() -> Route {
|
|
||||||
method(Method::POST)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* with `PUT` method guard.
|
/// Creates a new route with specified method guard.
|
||||||
///
|
///
|
||||||
/// ```
|
/// # Examples
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
/// In this example, one `GET /{project_id}` route is set up:
|
||||||
///
|
|
||||||
/// let app = App::new().service(
|
|
||||||
/// web::resource("/{project_id}")
|
|
||||||
/// .route(web::put().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `PUT` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn put() -> Route {
|
|
||||||
method(Method::PUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* with `PATCH` method guard.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
|
||||||
///
|
|
||||||
/// let app = App::new().service(
|
|
||||||
/// web::resource("/{project_id}")
|
|
||||||
/// .route(web::patch().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `PATCH` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn patch() -> Route {
|
|
||||||
method(Method::PATCH)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* with `DELETE` method guard.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
|
||||||
///
|
|
||||||
/// let app = App::new().service(
|
|
||||||
/// web::resource("/{project_id}")
|
|
||||||
/// .route(web::delete().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `DELETE` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn delete() -> Route {
|
|
||||||
method(Method::DELETE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* with `HEAD` method guard.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
|
||||||
///
|
|
||||||
/// let app = App::new().service(
|
|
||||||
/// web::resource("/{project_id}")
|
|
||||||
/// .route(web::head().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `HEAD` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn head() -> Route {
|
|
||||||
method(Method::HEAD)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* with `TRACE` method guard.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use actix_web::{web, App, HttpResponse};
|
|
||||||
///
|
|
||||||
/// let app = App::new().service(
|
|
||||||
/// web::resource("/{project_id}")
|
|
||||||
/// .route(web::trace().to(|| HttpResponse::Ok()))
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In the above example, one `HEAD` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn trace() -> Route {
|
|
||||||
method(Method::TRACE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create *route* and add method guard.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_web::{web, http, App, HttpResponse};
|
/// use actix_web::{web, http, App, HttpResponse};
|
||||||
@ -221,15 +121,11 @@ pub fn trace() -> Route {
|
|||||||
/// .route(web::method(http::Method::GET).to(|| HttpResponse::Ok()))
|
/// .route(web::method(http::Method::GET).to(|| HttpResponse::Ok()))
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
/// In the above example, one `GET` route gets added:
|
|
||||||
/// * /{project_id}
|
|
||||||
///
|
|
||||||
pub fn method(method: Method) -> Route {
|
pub fn method(method: Method) -> Route {
|
||||||
Route::new().method(method)
|
Route::new().method(method)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new route and add handler.
|
/// Creates a new any-method route with handler.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_web::{web, App, HttpResponse, Responder};
|
/// use actix_web::{web, App, HttpResponse, Responder};
|
||||||
@ -253,7 +149,7 @@ where
|
|||||||
Route::new().to(handler)
|
Route::new().to(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create raw service for a specific path.
|
/// Creates a raw service for a specific path.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use actix_web::{dev, web, guard, App, Error, HttpResponse};
|
/// use actix_web::{dev, web, guard, App, Error, HttpResponse};
|
||||||
@ -272,8 +168,8 @@ pub fn service<T: IntoPatterns>(path: T) -> WebService {
|
|||||||
WebService::new(path)
|
WebService::new(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute blocking function on a thread pool, returns future that resolves
|
/// Executes blocking function on a thread pool, returns future that resolves to result of the
|
||||||
/// to result of the function execution.
|
/// function execution.
|
||||||
pub fn block<F, R>(f: F) -> impl Future<Output = Result<R, BlockingError>>
|
pub fn block<F, R>(f: F) -> impl Future<Output = Result<R, BlockingError>>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> R + Send + 'static,
|
F: FnOnce() -> R + Send + 'static,
|
||||||
|
Loading…
Reference in New Issue
Block a user