1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-09-22 03:20:07 +00:00

refactor ResponseError trait

This commit is contained in:
Nikolay Kim 2019-11-26 16:07:39 +06:00
parent 4dc31aac93
commit f73f97353b
11 changed files with 105 additions and 111 deletions

View file

@ -4,6 +4,8 @@
replace `fn` with `async fn` to convert sync handler to async replace `fn` with `async fn` to convert sync handler to async
* `TestServer::new()` renamed to `TestServer::start()`
## 1.0.1 ## 1.0.1

View file

@ -26,16 +26,15 @@ Actix web is a simple, pragmatic and extremely fast web framework for Rust.
## Example ## Example
```rust ```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 { async fn index(info: web::Path<(u32, String)>) -> impl Responder {
format!("Hello {}! id:{}", info.1, info.0) format!("Hello {}! id:{}", info.1, info.0)
} }
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
HttpServer::new( HttpServer::new(|| App::new().service(index))
|| App::new().service(
web::resource("/{id}/{name}/index.html").to(index)))
.bind("127.0.0.1:8080")? .bind("127.0.0.1:8080")?
.run() .run()
} }

View file

@ -93,6 +93,10 @@ pub enum CorsError {
} }
impl ResponseError for CorsError { impl ResponseError for CorsError {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
fn error_response(&self) -> HttpResponse { fn error_response(&self) -> HttpResponse {
HttpResponse::with_body(StatusCode::BAD_REQUEST, format!("{}", self).into()) HttpResponse::with_body(StatusCode::BAD_REQUEST, format!("{}", self).into())
} }

View file

@ -35,7 +35,7 @@ pub enum UriSegmentError {
/// Return `BadRequest` for `UriSegmentError` /// Return `BadRequest` for `UriSegmentError`
impl ResponseError for UriSegmentError { impl ResponseError for UriSegmentError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
HttpResponse::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }

View file

@ -7,8 +7,7 @@ use trust_dns_resolver::error::ResolveError;
use open_ssl::ssl::{Error as SslError, HandshakeError}; use open_ssl::ssl::{Error as SslError, HandshakeError};
use crate::error::{Error, ParseError, ResponseError}; use crate::error::{Error, ParseError, ResponseError};
use crate::http::Error as HttpError; use crate::http::{Error as HttpError, StatusCode};
use crate::response::Response;
/// A set of errors that can occur while connecting to an HTTP host /// A set of errors that can occur while connecting to an HTTP host
#[derive(Debug, Display, From)] #[derive(Debug, Display, From)]
@ -117,15 +116,14 @@ pub enum SendRequestError {
/// Convert `SendRequestError` to a server `Response` /// Convert `SendRequestError` to a server `Response`
impl ResponseError for SendRequestError { impl ResponseError for SendRequestError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
match *self { match *self {
SendRequestError::Connect(ConnectError::Timeout) => { SendRequestError::Connect(ConnectError::Timeout) => {
Response::GatewayTimeout() StatusCode::GATEWAY_TIMEOUT
} }
SendRequestError::Connect(_) => Response::BadGateway(), SendRequestError::Connect(_) => StatusCode::BAD_REQUEST,
_ => Response::InternalServerError(), _ => StatusCode::INTERNAL_SERVER_ERROR,
} }
.into()
} }
} }

View file

@ -59,16 +59,18 @@ impl Error {
/// Error that can be converted to `Response` /// Error that can be converted to `Response`
pub trait ResponseError: fmt::Debug + fmt::Display { 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 /// Create response for error
/// ///
/// Internal server error is generated by default. /// Internal server error is generated by default.
fn error_response(&self) -> Response { fn error_response(&self) -> Response {
Response::new(StatusCode::INTERNAL_SERVER_ERROR) let mut resp = Response::new(self.status_code());
}
/// Constructs an error response
fn render_response(&self) -> Response {
let mut resp = self.error_response();
let mut buf = BytesMut::new(); let mut buf = BytesMut::new();
let _ = write!(Writer(&mut buf), "{}", self); let _ = write!(Writer(&mut buf), "{}", self);
resp.headers_mut().insert( resp.headers_mut().insert(
@ -156,10 +158,10 @@ impl<T: ResponseError + 'static> From<T> for Error {
/// Return `GATEWAY_TIMEOUT` for `TimeoutError` /// Return `GATEWAY_TIMEOUT` for `TimeoutError`
impl<E: ResponseError> ResponseError for TimeoutError<E> { impl<E: ResponseError> ResponseError for TimeoutError<E> {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
match self { match self {
TimeoutError::Service(e) => e.error_response(), TimeoutError::Service(e) => e.status_code(),
TimeoutError::Timeout => Response::new(StatusCode::GATEWAY_TIMEOUT), TimeoutError::Timeout => StatusCode::GATEWAY_TIMEOUT,
} }
} }
} }
@ -187,8 +189,8 @@ impl<T: std::fmt::Debug> ResponseError for open_ssl::ssl::HandshakeError<T> {}
/// Return `BAD_REQUEST` for `de::value::Error` /// Return `BAD_REQUEST` for `de::value::Error`
impl ResponseError for DeError { impl ResponseError for DeError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -197,8 +199,8 @@ impl ResponseError for Canceled {}
/// Return `BAD_REQUEST` for `Utf8Error` /// Return `BAD_REQUEST` for `Utf8Error`
impl ResponseError for Utf8Error { impl ResponseError for Utf8Error {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -208,26 +210,26 @@ impl ResponseError for HttpError {}
/// Return `InternalServerError` for `io::Error` /// Return `InternalServerError` for `io::Error`
impl ResponseError for io::Error { impl ResponseError for io::Error {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
match self.kind() { match self.kind() {
io::ErrorKind::NotFound => Response::new(StatusCode::NOT_FOUND), io::ErrorKind::NotFound => StatusCode::NOT_FOUND,
io::ErrorKind::PermissionDenied => Response::new(StatusCode::FORBIDDEN), io::ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
_ => Response::new(StatusCode::INTERNAL_SERVER_ERROR), _ => StatusCode::INTERNAL_SERVER_ERROR,
} }
} }
} }
/// `BadRequest` for `InvalidHeaderValue` /// `BadRequest` for `InvalidHeaderValue`
impl ResponseError for header::InvalidHeaderValue { impl ResponseError for header::InvalidHeaderValue {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
/// `BadRequest` for `InvalidHeaderValue` /// `BadRequest` for `InvalidHeaderValue`
impl ResponseError for header::InvalidHeaderValueBytes { impl ResponseError for header::InvalidHeaderValueBytes {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -270,8 +272,8 @@ pub enum ParseError {
/// Return `BadRequest` for `ParseError` /// Return `BadRequest` for `ParseError`
impl ResponseError for ParseError { impl ResponseError for ParseError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -371,18 +373,18 @@ impl From<Canceled> for PayloadError {
/// - `Overflow` returns `PayloadTooLarge` /// - `Overflow` returns `PayloadTooLarge`
/// - Other errors returns `BadRequest` /// - Other errors returns `BadRequest`
impl ResponseError for PayloadError { impl ResponseError for PayloadError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
match *self { match *self {
PayloadError::Overflow => Response::new(StatusCode::PAYLOAD_TOO_LARGE), PayloadError::Overflow => StatusCode::PAYLOAD_TOO_LARGE,
_ => Response::new(StatusCode::BAD_REQUEST), _ => StatusCode::BAD_REQUEST,
} }
} }
} }
/// Return `BadRequest` for `cookie::ParseError` /// Return `BadRequest` for `cookie::ParseError`
impl ResponseError for crate::cookie::ParseError { impl ResponseError for crate::cookie::ParseError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -446,8 +448,8 @@ pub enum ContentTypeError {
/// Return `BadRequest` for `ContentTypeError` /// Return `BadRequest` for `ContentTypeError`
impl ResponseError for ContentTypeError { impl ResponseError for ContentTypeError {
fn error_response(&self) -> Response { fn status_code(&self) -> StatusCode {
Response::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
@ -517,6 +519,19 @@ impl<T> ResponseError for InternalError<T>
where where
T: fmt::Debug + fmt::Display + 'static, 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 { fn error_response(&self) -> Response {
match self.status { match self.status {
InternalErrorType::Status(st) => { 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 /// Convert Response to a Error
@ -947,11 +957,7 @@ mod failure_integration {
use super::*; use super::*;
/// Compatibility for `failure::Error` /// Compatibility for `failure::Error`
impl ResponseError for failure::Error { impl ResponseError for failure::Error {}
fn error_response(&self) -> Response {
Response::new(StatusCode::INTERNAL_SERVER_ERROR)
}
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -53,7 +53,7 @@ impl Response<Body> {
/// Constructs an error response /// Constructs an error response
#[inline] #[inline]
pub fn from_error(error: Error) -> Response { 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 { if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR {
error!("Internal Server Error: {:?}", error); error!("Internal Server Error: {:?}", error);
} }

View file

@ -1,7 +1,7 @@
//! Error and Result module //! Error and Result module
use actix_web::error::{ParseError, PayloadError}; use actix_web::error::{ParseError, PayloadError};
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::{HttpResponse, ResponseError}; use actix_web::ResponseError;
use derive_more::{Display, From}; use derive_more::{Display, From};
/// A set of errors that can occur during parsing multipart streams /// A set of errors that can occur during parsing multipart streams
@ -35,14 +35,15 @@ pub enum MultipartError {
/// Return `BadRequest` for `MultipartError` /// Return `BadRequest` for `MultipartError`
impl ResponseError for MultipartError { impl ResponseError for MultipartError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
HttpResponse::new(StatusCode::BAD_REQUEST) StatusCode::BAD_REQUEST
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use actix_web::HttpResponse;
#[test] #[test]
fn test_multipart_error() { fn test_multipart_error() {

View file

@ -6,7 +6,7 @@ pub use actix_http::error::PayloadError;
pub use actix_http::ws::HandshakeError as WsHandshakeError; pub use actix_http::ws::HandshakeError as WsHandshakeError;
pub use actix_http::ws::ProtocolError as WsProtocolError; 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 serde_json::error::Error as JsonError;
use actix_http::http::{header::HeaderValue, Error as HttpError, StatusCode}; use actix_http::http::{header::HeaderValue, Error as HttpError, StatusCode};
@ -68,8 +68,4 @@ pub enum JsonPayloadError {
} }
/// Return `InternalServerError` for `JsonPayloadError` /// Return `InternalServerError` for `JsonPayloadError`
impl ResponseError for JsonPayloadError { impl ResponseError for JsonPayloadError {}
fn error_response(&self) -> Response {
Response::new(StatusCode::INTERNAL_SERVER_ERROR)
}
}

View file

@ -54,15 +54,11 @@ pub enum UrlencodedError {
/// Return `BadRequest` for `UrlencodedError` /// Return `BadRequest` for `UrlencodedError`
impl ResponseError for UrlencodedError { impl ResponseError for UrlencodedError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
match *self { match *self {
UrlencodedError::Overflow { .. } => { UrlencodedError::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
HttpResponse::new(StatusCode::PAYLOAD_TOO_LARGE) UrlencodedError::UnknownLength => StatusCode::LENGTH_REQUIRED,
} _ => StatusCode::BAD_REQUEST,
UrlencodedError::UnknownLength => {
HttpResponse::new(StatusCode::LENGTH_REQUIRED)
}
_ => HttpResponse::new(StatusCode::BAD_REQUEST),
} }
} }
} }
@ -106,10 +102,8 @@ pub enum PathError {
/// Return `BadRequest` for `PathError` /// Return `BadRequest` for `PathError`
impl ResponseError for PathError { impl ResponseError for PathError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
match *self { StatusCode::BAD_REQUEST
PathError::Deserialize(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
}
} }
} }
@ -123,12 +117,8 @@ pub enum QueryPayloadError {
/// Return `BadRequest` for `QueryPayloadError` /// Return `BadRequest` for `QueryPayloadError`
impl ResponseError for QueryPayloadError { impl ResponseError for QueryPayloadError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
match *self { StatusCode::BAD_REQUEST
QueryPayloadError::Deserialize(_) => {
HttpResponse::new(StatusCode::BAD_REQUEST)
}
}
} }
} }
@ -152,12 +142,10 @@ pub enum ReadlinesError {
/// Return `BadRequest` for `ReadlinesError` /// Return `BadRequest` for `ReadlinesError`
impl ResponseError for ReadlinesError { impl ResponseError for ReadlinesError {
fn error_response(&self) -> HttpResponse { fn status_code(&self) -> StatusCode {
match *self { match *self {
ReadlinesError::LimitOverflow => { ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
HttpResponse::new(StatusCode::PAYLOAD_TOO_LARGE) _ => StatusCode::BAD_REQUEST,
}
_ => HttpResponse::new(StatusCode::BAD_REQUEST),
} }
} }
} }

View file

@ -63,7 +63,7 @@
//! * SSL support with OpenSSL or `native-tls` //! * SSL support with OpenSSL or `native-tls`
//! * Middlewares (`Logger`, `Session`, `CORS`, `DefaultHeaders`) //! * Middlewares (`Logger`, `Session`, `CORS`, `DefaultHeaders`)
//! * Supports [Actix actor framework](https://github.com/actix/actix) //! * 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 //! ## Package feature
//! //!