mirror of https://github.com/fafhrd91/actix-web
Fix error body propagation in Response::from_error.
This commit is contained in:
parent
53da55aa3c
commit
565239bd0b
|
@ -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};
|
||||
|
@ -52,12 +52,8 @@ impl Response<Body> {
|
|||
#[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"));
|
||||
resp.error = Some(error);
|
||||
resp.set_body(Body::from(buf))
|
||||
resp
|
||||
}
|
||||
|
||||
/// Convert response to response with body
|
||||
|
@ -297,18 +293,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
|
||||
|
|
|
@ -64,7 +64,7 @@ where
|
|||
InitError = (),
|
||||
>,
|
||||
{
|
||||
/// Set application data. Applicatin data could be accessed
|
||||
/// Set application data. Application data could be accessed
|
||||
/// by using `Data<T>` extractor where `T` is data type.
|
||||
///
|
||||
/// **Note**: http server accepts an application factory rather than
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) trait DataFactoryResult {
|
|||
/// during application configuration process
|
||||
/// with `App::data()` method.
|
||||
///
|
||||
/// Applicatin data could be accessed by using `Data<T>`
|
||||
/// Application data could be accessed by using `Data<T>`
|
||||
/// extractor where `T` is data type.
|
||||
///
|
||||
/// **Note**: http server accepts an application factory rather than
|
||||
|
|
|
@ -31,7 +31,7 @@ pub enum UrlencodedError {
|
|||
#[display(fmt = "Can not decode chunked transfer encoding")]
|
||||
Chunked,
|
||||
/// Payload size is bigger than allowed. (default: 256kB)
|
||||
#[display(fmt = "Urlencoded payload size is bigger than allowed. (default: 256kB)")]
|
||||
#[display(fmt = "Urlencoded payload size is bigger than allowed (default: 256kB)")]
|
||||
Overflow,
|
||||
/// Payload size is now known
|
||||
#[display(fmt = "Payload size is now known")]
|
||||
|
@ -66,7 +66,7 @@ impl ResponseError for UrlencodedError {
|
|||
#[derive(Debug, Display, From)]
|
||||
pub enum JsonPayloadError {
|
||||
/// Payload size is bigger than allowed. (default: 32kB)
|
||||
#[display(fmt = "Json payload size is bigger than allowed.")]
|
||||
#[display(fmt = "Json payload size is bigger than allowed")]
|
||||
Overflow,
|
||||
/// Content type error
|
||||
#[display(fmt = "Content type error")]
|
||||
|
|
|
@ -365,8 +365,10 @@ mod tests {
|
|||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use super::*;
|
||||
use crate::error::InternalError;
|
||||
use crate::http::header;
|
||||
use crate::test::{block_on, TestRequest};
|
||||
use crate::HttpResponse;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct MyObject {
|
||||
|
@ -405,6 +407,37 @@ mod tests {
|
|||
assert_eq!(resp.body().bin_ref(), b"{\"name\":\"test\"}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_error_responder() {
|
||||
let (req, mut pl) = TestRequest::default()
|
||||
.header(
|
||||
header::CONTENT_TYPE,
|
||||
header::HeaderValue::from_static("application/json"),
|
||||
)
|
||||
.header(
|
||||
header::CONTENT_LENGTH,
|
||||
header::HeaderValue::from_static("16"),
|
||||
)
|
||||
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
||||
.route_data(JsonConfig::default().limit(10).error_handler(|err, _| {
|
||||
let msg = MyObject {
|
||||
name: "invalid request".to_string(),
|
||||
};
|
||||
let resp = HttpResponse::BadRequest()
|
||||
.body(serde_json::to_string(&msg).unwrap());
|
||||
InternalError::from_response(err, resp).into()
|
||||
}))
|
||||
.to_http_parts();
|
||||
|
||||
let s = block_on(Json::<MyObject>::from_request(&req, &mut pl));
|
||||
let mut resp = Response::from_error(s.err().unwrap().into());
|
||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
let body = block_on(resp.take_body().concat2()).unwrap();
|
||||
let msg: MyObject = serde_json::from_slice(&body).unwrap();
|
||||
assert_eq!(msg.name, "invalid request");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract() {
|
||||
let (req, mut pl) = TestRequest::default()
|
||||
|
@ -443,7 +476,7 @@ mod tests {
|
|||
|
||||
let s = block_on(Json::<MyObject>::from_request(&req, &mut pl));
|
||||
assert!(format!("{}", s.err().unwrap())
|
||||
.contains("Json payload size is bigger than allowed."));
|
||||
.contains("Json payload size is bigger than allowed"));
|
||||
|
||||
let (req, mut pl) = TestRequest::default()
|
||||
.header(
|
||||
|
|
|
@ -107,7 +107,7 @@ impl TestServer {
|
|||
TestServerRuntime { addr, rt, client }
|
||||
}
|
||||
|
||||
/// Get firat available unused address
|
||||
/// Get first available unused address
|
||||
pub fn unused_addr() -> net::SocketAddr {
|
||||
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
let socket = TcpBuilder::new_v4().unwrap();
|
||||
|
|
Loading…
Reference in New Issue