1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-28 01:52:57 +01:00

fix failure Send+Sync compatibility

This commit is contained in:
Nikolay Kim 2018-06-21 10:45:24 +06:00
parent dbd093075d
commit c2c4a5ba3f
2 changed files with 61 additions and 23 deletions

View File

@ -24,7 +24,7 @@ pub use cookie::ParseError as CookieParseError;
use handler::Responder; use handler::Responder;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::{HttpResponse, InnerHttpResponse}; use httpresponse::{HttpResponse, HttpResponseParts};
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html) /// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
/// for actix web operations /// for actix web operations
@ -654,7 +654,7 @@ pub struct InternalError<T> {
enum InternalErrorType { enum InternalErrorType {
Status(StatusCode), Status(StatusCode),
Response(Mutex<Option<Box<InnerHttpResponse>>>), Response(Mutex<Option<HttpResponseParts>>),
} }
impl<T> InternalError<T> { impl<T> InternalError<T> {
@ -669,9 +669,7 @@ impl<T> InternalError<T> {
/// Create `InternalError` with predefined `HttpResponse`. /// Create `InternalError` with predefined `HttpResponse`.
pub fn from_response(cause: T, response: HttpResponse) -> Self { pub fn from_response(cause: T, response: HttpResponse) -> Self {
let mut resp = response.into_inner(); let resp = response.into_parts();
resp.drop_unsupported_body();
InternalError { InternalError {
cause, cause,
status: InternalErrorType::Response(Mutex::new(Some(resp))), status: InternalErrorType::Response(Mutex::new(Some(resp))),
@ -716,7 +714,7 @@ where
InternalErrorType::Status(st) => HttpResponse::new(st), InternalErrorType::Status(st) => HttpResponse::new(st),
InternalErrorType::Response(ref resp) => { InternalErrorType::Response(ref resp) => {
if let Some(resp) = resp.lock().unwrap().take() { if let Some(resp) = resp.lock().unwrap().take() {
HttpResponse::from_inner(resp) HttpResponse::from_parts(resp)
} else { } else {
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR) HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
} }

View File

@ -299,12 +299,15 @@ impl HttpResponse {
self.get_mut().write_capacity = cap; self.get_mut().write_capacity = cap;
} }
pub(crate) fn into_inner(mut self) -> Box<InnerHttpResponse> { pub(crate) fn into_parts(mut self) -> HttpResponseParts {
self.0.take().unwrap() self.0.take().unwrap().into_parts()
} }
pub(crate) fn from_inner(inner: Box<InnerHttpResponse>) -> HttpResponse { pub(crate) fn from_parts(parts: HttpResponseParts) -> HttpResponse {
HttpResponse(Some(inner), HttpResponsePool::pool()) HttpResponse(
Some(Box::new(InnerHttpResponse::from_parts(parts))),
HttpResponsePool::pool(),
)
} }
} }
@ -880,12 +883,12 @@ impl<'a, S> From<&'a HttpRequest<S>> for HttpResponseBuilder {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InnerHttpResponse { struct InnerHttpResponse {
version: Option<Version>, version: Option<Version>,
headers: HeaderMap, headers: HeaderMap,
status: StatusCode, status: StatusCode,
reason: Option<&'static str>, reason: Option<&'static str>,
pub(crate) body: Body, body: Body,
chunked: Option<bool>, chunked: Option<bool>,
encoding: Option<ContentEncoding>, encoding: Option<ContentEncoding>,
connection_type: Option<ConnectionType>, connection_type: Option<ConnectionType>,
@ -894,10 +897,16 @@ pub(crate) struct InnerHttpResponse {
error: Option<Error>, error: Option<Error>,
} }
/// This is here only because `failure::Fail: Send + Sync` which looks insane to me pub(crate) struct HttpResponseParts {
unsafe impl Sync for InnerHttpResponse {} version: Option<Version>,
/// This is here only because `failure::Fail: Send + Sync` which looks insane to me headers: HeaderMap,
unsafe impl Send for InnerHttpResponse {} status: StatusCode,
reason: Option<&'static str>,
body: Option<Bytes>,
encoding: Option<ContentEncoding>,
connection_type: Option<ConnectionType>,
error: Option<Error>,
}
impl InnerHttpResponse { impl InnerHttpResponse {
#[inline] #[inline]
@ -918,16 +927,47 @@ impl InnerHttpResponse {
} }
/// This is for failure, we can not have Send + Sync on Streaming and Actor response /// This is for failure, we can not have Send + Sync on Streaming and Actor response
pub(crate) fn drop_unsupported_body(&mut self) { fn into_parts(mut self) -> HttpResponseParts {
let body = mem::replace(&mut self.body, Body::Empty); let body = match mem::replace(&mut self.body, Body::Empty) {
match body { Body::Empty => None,
Body::Empty => (), Body::Binary(mut bin) => Some(bin.take()),
Body::Binary(mut bin) => {
self.body = Body::Binary(bin.take().into());
}
Body::Streaming(_) | Body::Actor(_) => { Body::Streaming(_) | Body::Actor(_) => {
error!("Streaming or Actor body is not support by error response"); error!("Streaming or Actor body is not support by error response");
None
} }
};
HttpResponseParts {
body,
version: self.version,
headers: self.headers,
status: self.status,
reason: self.reason,
encoding: self.encoding,
connection_type: self.connection_type,
error: self.error,
}
}
fn from_parts(parts: HttpResponseParts) -> InnerHttpResponse {
let body = if let Some(ref body) = parts.body {
Body::Binary(body.clone().into())
} else {
Body::Empty
};
InnerHttpResponse {
body,
status: parts.status,
version: parts.version,
headers: parts.headers,
reason: parts.reason,
chunked: None,
encoding: parts.encoding,
connection_type: parts.connection_type,
response_size: 0,
write_capacity: MAX_WRITE_BUFFER_SIZE,
error: parts.error,
} }
} }
} }