1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-06-25 06:39:22 +02:00

Fix body propagation in Response::from_error. #760

This commit is contained in:
Nikolay Kim
2019-04-10 12:43:31 -07:00
parent 9bb40c249f
commit 9d82d4dfb9
10 changed files with 92 additions and 27 deletions

View File

@ -1,11 +1,13 @@
//! Error and Result module
use std::cell::RefCell;
use std::io::Write;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::{fmt, io, result};
pub use actix_threadpool::BlockingError;
use actix_utils::timeout::TimeoutError;
use bytes::BytesMut;
use derive_more::{Display, From};
use futures::Canceled;
use http::uri::InvalidUri;
@ -17,7 +19,9 @@ use serde_urlencoded::ser::Error as FormError;
use tokio_timer::Error as TimerError;
// re-export for convinience
use crate::body::Body;
pub use crate::cookie::ParseError as CookieParseError;
use crate::helpers::Writer;
use crate::response::Response;
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
@ -57,6 +61,18 @@ pub trait ResponseError: fmt::Debug + fmt::Display {
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 buf = BytesMut::new();
let _ = write!(Writer(&mut buf), "{}", self);
resp.headers_mut().insert(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"),
);
resp.set_body(Body::from(buf))
}
}
impl fmt::Display for Error {
@ -477,7 +493,16 @@ where
{
fn error_response(&self) -> Response {
match self.status {
InternalErrorType::Status(st) => Response::new(st),
InternalErrorType::Status(st) => {
let mut res = Response::new(st);
let mut buf = BytesMut::new();
let _ = write!(Writer(&mut buf), "{}", self);
res.headers_mut().insert(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"),
);
res.set_body(Body::from(buf))
}
InternalErrorType::Response(ref resp) => {
if let Some(resp) = resp.borrow_mut().take() {
resp
@ -487,6 +512,11 @@ where
}
}
}
/// Constructs an error response
fn render_response(&self) -> Response {
self.error_response()
}
}
/// Convert Response to a Error

View File

@ -1,6 +1,7 @@
use std::{io, mem, ptr, slice};
use bytes::{BufMut, BytesMut};
use http::Version;
use std::{mem, ptr, slice};
const DEC_DIGITS_LUT: &[u8] = b"0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
@ -167,6 +168,18 @@ pub(crate) fn convert_usize(mut n: usize, bytes: &mut BytesMut) {
}
}
pub(crate) struct Writer<'a>(pub &'a mut BytesMut);
impl<'a> io::Write for Writer<'a> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -1,7 +1,7 @@
//! Http response
use std::cell::{Ref, RefMut};
use std::io::Write;
use std::{fmt, io, str};
use std::{fmt, str};
use bytes::{BufMut, Bytes, BytesMut};
use futures::future::{ok, FutureResult, IntoFuture};
@ -51,13 +51,9 @@ impl Response<Body> {
/// Constructs an error response
#[inline]
pub fn from_error(error: Error) -> Response {
let mut resp = error.as_response_error().error_response();
let mut buf = BytesMut::new();
let _ = write!(Writer(&mut buf), "{}", error);
resp.headers_mut()
.insert(header::CONTENT_TYPE, HeaderValue::from_static("text/plain"));
let mut resp = error.as_response_error().render_response();
resp.error = Some(error);
resp.set_body(Body::from(buf))
resp
}
/// Convert response to response with body
@ -309,18 +305,6 @@ impl<'a> Iterator for CookieIter<'a> {
}
}
pub struct Writer<'a>(pub &'a mut BytesMut);
impl<'a> io::Write for Writer<'a> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
/// An HTTP response builder
///
/// This type can be used to construct an instance of `Response` through a