diff --git a/MIGRATION.md b/MIGRATION.md index 675dc61ed..dd3a1b043 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -4,6 +4,8 @@ replace `fn` with `async fn` to convert sync handler to async +* `TestServer::new()` renamed to `TestServer::start()` + ## 1.0.1 @@ -41,52 +43,52 @@ * Extractor configuration. In version 1.0 this is handled with the new `Data` mechanism for both setting and retrieving the configuration instead of - + ```rust - + #[derive(Default)] struct ExtractorConfig { config: String, } - + impl FromRequest for YourExtractor { type Config = ExtractorConfig; type Result = Result; - + fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { println!("use the config: {:?}", cfg.config); ... } } - + App::new().resource("/route_with_config", |r| { r.post().with_config(handler_fn, |cfg| { cfg.0.config = "test".to_string(); }) }) - + ``` - + use the HttpRequest to get the configuration like any other `Data` with `req.app_data::()` and set it with the `data()` method on the `resource` - + ```rust #[derive(Default)] struct ExtractorConfig { config: String, } - + impl FromRequest for YourExtractor { type Error = Error; type Future = Result; type Config = ExtractorConfig; - + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let cfg = req.app_data::(); println!("config data?: {:?}", cfg.unwrap().role); ... } } - + App::new().service( resource("/route_with_config") .data(ExtractorConfig { @@ -95,7 +97,7 @@ .route(post().to(handler_fn)), ) ``` - + * Resource registration. 1.0 version uses generalized resource registration via `.service()` method. @@ -386,9 +388,9 @@ * `HttpRequest` does not implement `Stream` anymore. If you need to read request payload use `HttpMessage::payload()` method. - + instead of - + ```rust fn index(req: HttpRequest) -> impl Responder { req @@ -414,8 +416,8 @@ trait uses `&HttpRequest` instead of `&mut HttpRequest`. * Removed `Route::with2()` and `Route::with3()` use tuple of extractors instead. - - instead of + + instead of ```rust fn index(query: Query<..>, info: Json impl Responder {} @@ -431,7 +433,7 @@ * `Handler::handle()` accepts reference to `HttpRequest<_>` instead of value -* Removed deprecated `HttpServer::threads()`, use +* Removed deprecated `HttpServer::threads()`, use [HttpServer::workers()](https://actix.rs/actix-web/actix_web/server/struct.HttpServer.html#method.workers) instead. * Renamed `client::ClientConnectorError::Connector` to @@ -440,7 +442,7 @@ * `Route::with()` does not return `ExtractorConfig`, to configure extractor use `Route::with_config()` - instead of + instead of ```rust fn main() { @@ -451,11 +453,11 @@ }); } ``` - - use - + + use + ```rust - + fn main() { let app = App::new().resource("/index.html", |r| { r.method(http::Method::GET) @@ -485,12 +487,12 @@ * `HttpRequest::extensions()` returns read only reference to the request's Extension `HttpRequest::extensions_mut()` returns mutable reference. -* Instead of +* Instead of `use actix_web::middleware::{ CookieSessionBackend, CookieSessionError, RequestSession, Session, SessionBackend, SessionImpl, SessionStorage};` - + use `actix_web::middleware::session` `use actix_web::middleware::session{CookieSessionBackend, CookieSessionError, diff --git a/README.md b/README.md index 00bb3ec4e..4c0553e38 100644 --- a/README.md +++ b/README.md @@ -26,16 +26,15 @@ Actix web is a simple, pragmatic and extremely fast web framework for Rust. ## Example ```rust -use actix_web::{web, App, HttpServer, Responder}; +use actix_web::{get, App, HttpServer, Responder}; +#[get("/{id}/{name}/index.html")] async fn index(info: web::Path<(u32, String)>) -> impl Responder { format!("Hello {}! id:{}", info.1, info.0) } fn main() -> std::io::Result<()> { - HttpServer::new( - || App::new().service( - web::resource("/{id}/{name}/index.html").to(index))) + HttpServer::new(|| App::new().service(index)) .bind("127.0.0.1:8080")? .run() } diff --git a/actix-cors/src/lib.rs b/actix-cors/src/lib.rs index 551e3bb4d..d3607aa8e 100644 --- a/actix-cors/src/lib.rs +++ b/actix-cors/src/lib.rs @@ -93,6 +93,10 @@ pub enum CorsError { } impl ResponseError for CorsError { + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST + } + fn error_response(&self) -> HttpResponse { HttpResponse::with_body(StatusCode::BAD_REQUEST, format!("{}", self).into()) } diff --git a/actix-files/src/error.rs b/actix-files/src/error.rs index ca99fa813..49a46e58d 100644 --- a/actix-files/src/error.rs +++ b/actix-files/src/error.rs @@ -35,7 +35,7 @@ pub enum UriSegmentError { /// Return `BadRequest` for `UriSegmentError` impl ResponseError for UriSegmentError { - fn error_response(&self) -> HttpResponse { - HttpResponse::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } diff --git a/actix-http/src/client/error.rs b/actix-http/src/client/error.rs index 75f7935f2..ee568e8be 100644 --- a/actix-http/src/client/error.rs +++ b/actix-http/src/client/error.rs @@ -7,8 +7,7 @@ use trust_dns_resolver::error::ResolveError; use open_ssl::ssl::{Error as SslError, HandshakeError}; use crate::error::{Error, ParseError, ResponseError}; -use crate::http::Error as HttpError; -use crate::response::Response; +use crate::http::{Error as HttpError, StatusCode}; /// A set of errors that can occur while connecting to an HTTP host #[derive(Debug, Display, From)] @@ -117,15 +116,14 @@ pub enum SendRequestError { /// Convert `SendRequestError` to a server `Response` impl ResponseError for SendRequestError { - fn error_response(&self) -> Response { + fn status_code(&self) -> StatusCode { match *self { SendRequestError::Connect(ConnectError::Timeout) => { - Response::GatewayTimeout() + StatusCode::GATEWAY_TIMEOUT } - SendRequestError::Connect(_) => Response::BadGateway(), - _ => Response::InternalServerError(), + SendRequestError::Connect(_) => StatusCode::BAD_REQUEST, + _ => StatusCode::INTERNAL_SERVER_ERROR, } - .into() } } diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index f1767cf19..587849bde 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -59,16 +59,18 @@ impl Error { /// Error that can be converted to `Response` pub trait ResponseError: fmt::Debug + fmt::Display { + /// Response's status code + /// + /// Internal server error is generated by default. + fn status_code(&self) -> StatusCode { + StatusCode::INTERNAL_SERVER_ERROR + } + /// Create response for error /// /// Internal server error is generated by default. fn error_response(&self) -> Response { - Response::new(StatusCode::INTERNAL_SERVER_ERROR) - } - - /// Constructs an error response - fn render_response(&self) -> Response { - let mut resp = self.error_response(); + let mut resp = Response::new(self.status_code()); let mut buf = BytesMut::new(); let _ = write!(Writer(&mut buf), "{}", self); resp.headers_mut().insert( @@ -156,10 +158,10 @@ impl From for Error { /// Return `GATEWAY_TIMEOUT` for `TimeoutError` impl ResponseError for TimeoutError { - fn error_response(&self) -> Response { + fn status_code(&self) -> StatusCode { match self { - TimeoutError::Service(e) => e.error_response(), - TimeoutError::Timeout => Response::new(StatusCode::GATEWAY_TIMEOUT), + TimeoutError::Service(e) => e.status_code(), + TimeoutError::Timeout => StatusCode::GATEWAY_TIMEOUT, } } } @@ -187,8 +189,8 @@ impl ResponseError for open_ssl::ssl::HandshakeError {} /// Return `BAD_REQUEST` for `de::value::Error` impl ResponseError for DeError { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -197,8 +199,8 @@ impl ResponseError for Canceled {} /// Return `BAD_REQUEST` for `Utf8Error` impl ResponseError for Utf8Error { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -208,26 +210,26 @@ impl ResponseError for HttpError {} /// Return `InternalServerError` for `io::Error` impl ResponseError for io::Error { - fn error_response(&self) -> Response { + fn status_code(&self) -> StatusCode { match self.kind() { - io::ErrorKind::NotFound => Response::new(StatusCode::NOT_FOUND), - io::ErrorKind::PermissionDenied => Response::new(StatusCode::FORBIDDEN), - _ => Response::new(StatusCode::INTERNAL_SERVER_ERROR), + io::ErrorKind::NotFound => StatusCode::NOT_FOUND, + io::ErrorKind::PermissionDenied => StatusCode::FORBIDDEN, + _ => StatusCode::INTERNAL_SERVER_ERROR, } } } /// `BadRequest` for `InvalidHeaderValue` impl ResponseError for header::InvalidHeaderValue { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } /// `BadRequest` for `InvalidHeaderValue` impl ResponseError for header::InvalidHeaderValueBytes { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -270,8 +272,8 @@ pub enum ParseError { /// Return `BadRequest` for `ParseError` impl ResponseError for ParseError { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -371,18 +373,18 @@ impl From for PayloadError { /// - `Overflow` returns `PayloadTooLarge` /// - Other errors returns `BadRequest` impl ResponseError for PayloadError { - fn error_response(&self) -> Response { + fn status_code(&self) -> StatusCode { match *self { - PayloadError::Overflow => Response::new(StatusCode::PAYLOAD_TOO_LARGE), - _ => Response::new(StatusCode::BAD_REQUEST), + PayloadError::Overflow => StatusCode::PAYLOAD_TOO_LARGE, + _ => StatusCode::BAD_REQUEST, } } } /// Return `BadRequest` for `cookie::ParseError` impl ResponseError for crate::cookie::ParseError { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -446,8 +448,8 @@ pub enum ContentTypeError { /// Return `BadRequest` for `ContentTypeError` impl ResponseError for ContentTypeError { - fn error_response(&self) -> Response { - Response::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -517,6 +519,19 @@ impl ResponseError for InternalError where T: fmt::Debug + fmt::Display + 'static, { + fn status_code(&self) -> StatusCode { + match self.status { + InternalErrorType::Status(st) => st, + InternalErrorType::Response(ref resp) => { + if let Some(resp) = resp.borrow().as_ref() { + resp.head().status + } else { + StatusCode::INTERNAL_SERVER_ERROR + } + } + } + } + fn error_response(&self) -> Response { match self.status { InternalErrorType::Status(st) => { @@ -538,11 +553,6 @@ where } } } - - /// Constructs an error response - fn render_response(&self) -> Response { - self.error_response() - } } /// Convert Response to a Error @@ -947,11 +957,7 @@ mod failure_integration { use super::*; /// Compatibility for `failure::Error` - impl ResponseError for failure::Error { - fn error_response(&self) -> Response { - Response::new(StatusCode::INTERNAL_SERVER_ERROR) - } - } + impl ResponseError for failure::Error {} } #[cfg(test)] diff --git a/actix-http/src/response.rs b/actix-http/src/response.rs index 5eb0228dc..e9147aa4b 100644 --- a/actix-http/src/response.rs +++ b/actix-http/src/response.rs @@ -53,7 +53,7 @@ impl Response { /// Constructs an error response #[inline] pub fn from_error(error: Error) -> Response { - let mut resp = error.as_response_error().render_response(); + let mut resp = error.as_response_error().error_response(); if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR { error!("Internal Server Error: {:?}", error); } diff --git a/actix-multipart/src/error.rs b/actix-multipart/src/error.rs index 32c740a1a..6677f69c7 100644 --- a/actix-multipart/src/error.rs +++ b/actix-multipart/src/error.rs @@ -1,7 +1,7 @@ //! Error and Result module use actix_web::error::{ParseError, PayloadError}; use actix_web::http::StatusCode; -use actix_web::{HttpResponse, ResponseError}; +use actix_web::ResponseError; use derive_more::{Display, From}; /// A set of errors that can occur during parsing multipart streams @@ -35,14 +35,15 @@ pub enum MultipartError { /// Return `BadRequest` for `MultipartError` impl ResponseError for MultipartError { - fn error_response(&self) -> HttpResponse { - HttpResponse::new(StatusCode::BAD_REQUEST) + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } #[cfg(test)] mod tests { use super::*; + use actix_web::HttpResponse; #[test] fn test_multipart_error() { diff --git a/awc/src/error.rs b/awc/src/error.rs index eb8d03e2b..8816c4075 100644 --- a/awc/src/error.rs +++ b/awc/src/error.rs @@ -6,7 +6,7 @@ pub use actix_http::error::PayloadError; pub use actix_http::ws::HandshakeError as WsHandshakeError; pub use actix_http::ws::ProtocolError as WsProtocolError; -use actix_http::{Response, ResponseError}; +use actix_http::ResponseError; use serde_json::error::Error as JsonError; use actix_http::http::{header::HeaderValue, Error as HttpError, StatusCode}; @@ -68,8 +68,4 @@ pub enum JsonPayloadError { } /// Return `InternalServerError` for `JsonPayloadError` -impl ResponseError for JsonPayloadError { - fn error_response(&self) -> Response { - Response::new(StatusCode::INTERNAL_SERVER_ERROR) - } -} +impl ResponseError for JsonPayloadError {} diff --git a/src/error.rs b/src/error.rs index a60276a7a..2eec7c51b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -54,15 +54,11 @@ pub enum UrlencodedError { /// Return `BadRequest` for `UrlencodedError` impl ResponseError for UrlencodedError { - fn error_response(&self) -> HttpResponse { + fn status_code(&self) -> StatusCode { match *self { - UrlencodedError::Overflow { .. } => { - HttpResponse::new(StatusCode::PAYLOAD_TOO_LARGE) - } - UrlencodedError::UnknownLength => { - HttpResponse::new(StatusCode::LENGTH_REQUIRED) - } - _ => HttpResponse::new(StatusCode::BAD_REQUEST), + UrlencodedError::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE, + UrlencodedError::UnknownLength => StatusCode::LENGTH_REQUIRED, + _ => StatusCode::BAD_REQUEST, } } } @@ -106,10 +102,8 @@ pub enum PathError { /// Return `BadRequest` for `PathError` impl ResponseError for PathError { - fn error_response(&self) -> HttpResponse { - match *self { - PathError::Deserialize(_) => HttpResponse::new(StatusCode::BAD_REQUEST), - } + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -123,12 +117,8 @@ pub enum QueryPayloadError { /// Return `BadRequest` for `QueryPayloadError` impl ResponseError for QueryPayloadError { - fn error_response(&self) -> HttpResponse { - match *self { - QueryPayloadError::Deserialize(_) => { - HttpResponse::new(StatusCode::BAD_REQUEST) - } - } + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST } } @@ -152,12 +142,10 @@ pub enum ReadlinesError { /// Return `BadRequest` for `ReadlinesError` impl ResponseError for ReadlinesError { - fn error_response(&self) -> HttpResponse { + fn status_code(&self) -> StatusCode { match *self { - ReadlinesError::LimitOverflow => { - HttpResponse::new(StatusCode::PAYLOAD_TOO_LARGE) - } - _ => HttpResponse::new(StatusCode::BAD_REQUEST), + ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE, + _ => StatusCode::BAD_REQUEST, } } } diff --git a/src/lib.rs b/src/lib.rs index 4d1facd8d..b7fd8d155 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! * SSL support with OpenSSL or `native-tls` //! * Middlewares (`Logger`, `Session`, `CORS`, `DefaultHeaders`) //! * Supports [Actix actor framework](https://github.com/actix/actix) -//! * Supported Rust version: 1.36 or later +//! * Supported Rust version: 1.39 or later //! //! ## Package feature //!