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

@ -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()
}
}

View file

@ -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<T: ResponseError + 'static> From<T> for Error {
/// Return `GATEWAY_TIMEOUT` for `TimeoutError`
impl<E: ResponseError> ResponseError for TimeoutError<E> {
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<T: std::fmt::Debug> ResponseError for open_ssl::ssl::HandshakeError<T> {}
/// 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<Canceled> 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<T> ResponseError for InternalError<T>
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)]

View file

@ -53,7 +53,7 @@ impl Response<Body> {
/// 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);
}