mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 09:42:40 +01:00
simplify server response type
This commit is contained in:
parent
3a4b16a6d5
commit
f0bd4d868e
@ -74,6 +74,8 @@ impl Default for ResponseHead {
|
|||||||
|
|
||||||
impl Head for ResponseHead {
|
impl Head for ResponseHead {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
|
self.reason = None;
|
||||||
|
self.version = None;
|
||||||
self.headers.clear();
|
self.headers.clear();
|
||||||
self.flags = MessageFlags::empty();
|
self.flags = MessageFlags::empty();
|
||||||
}
|
}
|
||||||
|
113
src/response.rs
113
src/response.rs
@ -12,6 +12,7 @@ use http::{Error as HttpError, HeaderMap, HttpTryFrom, StatusCode, Version};
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
|
use message::{Head, ResponseHead, MessageFlags};
|
||||||
use body::Body;
|
use body::Body;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use header::{ContentEncoding, Header, IntoHeaderValue};
|
use header::{ContentEncoding, Header, IntoHeaderValue};
|
||||||
@ -31,7 +32,7 @@ pub enum ConnectionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP Response
|
/// An HTTP Response
|
||||||
pub struct Response(Box<InnerResponse>, &'static ResponsePool);
|
pub struct Response(Box<InnerResponse>);
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -92,7 +93,6 @@ impl Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
pool: self.1,
|
|
||||||
response: Some(self.0),
|
response: Some(self.0),
|
||||||
err: None,
|
err: None,
|
||||||
cookies: jar,
|
cookies: jar,
|
||||||
@ -108,33 +108,33 @@ impl Response {
|
|||||||
/// Get the HTTP version of this response
|
/// Get the HTTP version of this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn version(&self) -> Option<Version> {
|
pub fn version(&self) -> Option<Version> {
|
||||||
self.get_ref().version
|
self.get_ref().head.version
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the headers from the response
|
/// Get the headers from the response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers(&self) -> &HeaderMap {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
&self.get_ref().headers
|
&self.get_ref().head.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the headers
|
/// Get a mutable reference to the headers
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
&mut self.get_mut().headers
|
&mut self.get_mut().head.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator for the cookies set by this response
|
/// Get an iterator for the cookies set by this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cookies(&self) -> CookieIter {
|
pub fn cookies(&self) -> CookieIter {
|
||||||
CookieIter {
|
CookieIter {
|
||||||
iter: self.get_ref().headers.get_all(header::SET_COOKIE).iter(),
|
iter: self.get_ref().head.headers.get_all(header::SET_COOKIE).iter(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a cookie to this response
|
/// Add a cookie to this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_cookie(&mut self, cookie: &Cookie) -> Result<(), HttpError> {
|
pub fn add_cookie(&mut self, cookie: &Cookie) -> Result<(), HttpError> {
|
||||||
let h = &mut self.get_mut().headers;
|
let h = &mut self.get_mut().head.headers;
|
||||||
HeaderValue::from_str(&cookie.to_string())
|
HeaderValue::from_str(&cookie.to_string())
|
||||||
.map(|c| {
|
.map(|c| {
|
||||||
h.append(header::SET_COOKIE, c);
|
h.append(header::SET_COOKIE, c);
|
||||||
@ -145,7 +145,7 @@ impl Response {
|
|||||||
/// the number of cookies removed.
|
/// the number of cookies removed.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn del_cookie(&mut self, name: &str) -> usize {
|
pub fn del_cookie(&mut self, name: &str) -> usize {
|
||||||
let h = &mut self.get_mut().headers;
|
let h = &mut self.get_mut().head.headers;
|
||||||
let vals: Vec<HeaderValue> = h
|
let vals: Vec<HeaderValue> = h
|
||||||
.get_all(header::SET_COOKIE)
|
.get_all(header::SET_COOKIE)
|
||||||
.iter()
|
.iter()
|
||||||
@ -171,23 +171,23 @@ impl Response {
|
|||||||
/// Get the response status code
|
/// Get the response status code
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn status(&self) -> StatusCode {
|
pub fn status(&self) -> StatusCode {
|
||||||
self.get_ref().status
|
self.get_ref().head.status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the `StatusCode` for this response
|
/// Set the `StatusCode` for this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn status_mut(&mut self) -> &mut StatusCode {
|
pub fn status_mut(&mut self) -> &mut StatusCode {
|
||||||
&mut self.get_mut().status
|
&mut self.get_mut().head.status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get custom reason for the response
|
/// Get custom reason for the response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reason(&self) -> &str {
|
pub fn reason(&self) -> &str {
|
||||||
if let Some(reason) = self.get_ref().reason {
|
if let Some(reason) = self.get_ref().head.reason {
|
||||||
reason
|
reason
|
||||||
} else {
|
} else {
|
||||||
self.get_ref()
|
self.get_ref()
|
||||||
.status
|
.head.status
|
||||||
.canonical_reason()
|
.canonical_reason()
|
||||||
.unwrap_or("<unknown status code>")
|
.unwrap_or("<unknown status code>")
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ impl Response {
|
|||||||
/// Set the custom reason for the response
|
/// Set the custom reason for the response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_reason(&mut self, reason: &'static str) -> &mut Self {
|
pub fn set_reason(&mut self, reason: &'static str) -> &mut Self {
|
||||||
self.get_mut().reason = Some(reason);
|
self.get_mut().head.reason = Some(reason);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ impl Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn release(self) {
|
pub(crate) fn release(self) {
|
||||||
self.1.release(self.0);
|
ResponsePool::release(self.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_parts(self) -> ResponseParts {
|
pub(crate) fn into_parts(self) -> ResponseParts {
|
||||||
@ -287,10 +287,7 @@ impl Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_parts(parts: ResponseParts) -> Response {
|
pub(crate) fn from_parts(parts: ResponseParts) -> Response {
|
||||||
Response(
|
Response(Box::new(InnerResponse::from_parts(parts)))
|
||||||
Box::new(InnerResponse::from_parts(parts)),
|
|
||||||
ResponsePool::get_pool(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,13 +296,13 @@ impl fmt::Debug for Response {
|
|||||||
let res = writeln!(
|
let res = writeln!(
|
||||||
f,
|
f,
|
||||||
"\nResponse {:?} {}{}",
|
"\nResponse {:?} {}{}",
|
||||||
self.get_ref().version,
|
self.get_ref().head.version,
|
||||||
self.get_ref().status,
|
self.get_ref().head.status,
|
||||||
self.get_ref().reason.unwrap_or("")
|
self.get_ref().head.reason.unwrap_or("")
|
||||||
);
|
);
|
||||||
let _ = writeln!(f, " encoding: {:?}", self.get_ref().encoding);
|
let _ = writeln!(f, " encoding: {:?}", self.get_ref().encoding);
|
||||||
let _ = writeln!(f, " headers:");
|
let _ = writeln!(f, " headers:");
|
||||||
for (key, val) in self.get_ref().headers.iter() {
|
for (key, val) in self.get_ref().head.headers.iter() {
|
||||||
let _ = writeln!(f, " {:?}: {:?}", key, val);
|
let _ = writeln!(f, " {:?}: {:?}", key, val);
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
@ -335,7 +332,6 @@ impl<'a> Iterator for CookieIter<'a> {
|
|||||||
/// This type can be used to construct an instance of `Response` through a
|
/// This type can be used to construct an instance of `Response` through a
|
||||||
/// builder-like pattern.
|
/// builder-like pattern.
|
||||||
pub struct ResponseBuilder {
|
pub struct ResponseBuilder {
|
||||||
pool: &'static ResponsePool,
|
|
||||||
response: Option<Box<InnerResponse>>,
|
response: Option<Box<InnerResponse>>,
|
||||||
err: Option<HttpError>,
|
err: Option<HttpError>,
|
||||||
cookies: Option<CookieJar>,
|
cookies: Option<CookieJar>,
|
||||||
@ -346,7 +342,7 @@ impl ResponseBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn status(&mut self, status: StatusCode) -> &mut Self {
|
pub fn status(&mut self, status: StatusCode) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
parts.status = status;
|
parts.head.status = status;
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -357,7 +353,7 @@ impl ResponseBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn version(&mut self, version: Version) -> &mut Self {
|
pub fn version(&mut self, version: Version) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
parts.version = Some(version);
|
parts.head.version = Some(version);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -382,7 +378,7 @@ impl ResponseBuilder {
|
|||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
match hdr.try_into() {
|
match hdr.try_into() {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.headers.append(H::name(), value);
|
parts.head.headers.append(H::name(), value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
}
|
}
|
||||||
@ -413,7 +409,7 @@ impl ResponseBuilder {
|
|||||||
match HeaderName::try_from(key) {
|
match HeaderName::try_from(key) {
|
||||||
Ok(key) => match value.try_into() {
|
Ok(key) => match value.try_into() {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.headers.append(key, value);
|
parts.head.headers.append(key, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
},
|
},
|
||||||
@ -427,7 +423,7 @@ impl ResponseBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn reason(&mut self, reason: &'static str) -> &mut Self {
|
pub fn reason(&mut self, reason: &'static str) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
parts.reason = Some(reason);
|
parts.head.reason = Some(reason);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -496,7 +492,7 @@ impl ResponseBuilder {
|
|||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
match HeaderValue::try_from(value) {
|
match HeaderValue::try_from(value) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.headers.insert(header::CONTENT_TYPE, value);
|
parts.head.headers.insert(header::CONTENT_TYPE, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
};
|
};
|
||||||
@ -620,13 +616,13 @@ impl ResponseBuilder {
|
|||||||
if let Some(ref jar) = self.cookies {
|
if let Some(ref jar) = self.cookies {
|
||||||
for cookie in jar.delta() {
|
for cookie in jar.delta() {
|
||||||
match HeaderValue::from_str(&cookie.to_string()) {
|
match HeaderValue::from_str(&cookie.to_string()) {
|
||||||
Ok(val) => response.headers.append(header::SET_COOKIE, val),
|
Ok(val) => response.head.headers.append(header::SET_COOKIE, val),
|
||||||
Err(e) => return Error::from(e).into(),
|
Err(e) => return Error::from(e).into(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.body = body.into();
|
response.body = body.into();
|
||||||
Response(response, self.pool)
|
Response(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -656,7 +652,7 @@ impl ResponseBuilder {
|
|||||||
Ok(body) => {
|
Ok(body) => {
|
||||||
let contains = if let Some(parts) = parts(&mut self.response, &self.err)
|
let contains = if let Some(parts) = parts(&mut self.response, &self.err)
|
||||||
{
|
{
|
||||||
parts.headers.contains_key(header::CONTENT_TYPE)
|
parts.head.headers.contains_key(header::CONTENT_TYPE)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
@ -681,7 +677,6 @@ impl ResponseBuilder {
|
|||||||
/// This method construct new `ResponseBuilder`
|
/// This method construct new `ResponseBuilder`
|
||||||
pub fn take(&mut self) -> ResponseBuilder {
|
pub fn take(&mut self) -> ResponseBuilder {
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
pool: self.pool,
|
|
||||||
response: self.response.take(),
|
response: self.response.take(),
|
||||||
err: self.err.take(),
|
err: self.err.take(),
|
||||||
cookies: self.cookies.take(),
|
cookies: self.cookies.take(),
|
||||||
@ -765,12 +760,8 @@ impl From<BytesMut> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct InnerResponse {
|
struct InnerResponse {
|
||||||
version: Option<Version>,
|
head: ResponseHead,
|
||||||
headers: HeaderMap,
|
|
||||||
status: StatusCode,
|
|
||||||
reason: Option<&'static str>,
|
|
||||||
body: Body,
|
body: Body,
|
||||||
chunked: Option<bool>,
|
chunked: Option<bool>,
|
||||||
encoding: Option<ContentEncoding>,
|
encoding: Option<ContentEncoding>,
|
||||||
@ -778,13 +769,11 @@ struct InnerResponse {
|
|||||||
write_capacity: usize,
|
write_capacity: usize,
|
||||||
response_size: u64,
|
response_size: u64,
|
||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
|
pool: &'static ResponsePool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ResponseParts {
|
pub(crate) struct ResponseParts {
|
||||||
version: Option<Version>,
|
head: ResponseHead,
|
||||||
headers: HeaderMap,
|
|
||||||
status: StatusCode,
|
|
||||||
reason: Option<&'static str>,
|
|
||||||
body: Option<Bytes>,
|
body: Option<Bytes>,
|
||||||
encoding: Option<ContentEncoding>,
|
encoding: Option<ContentEncoding>,
|
||||||
connection_type: Option<ConnectionType>,
|
connection_type: Option<ConnectionType>,
|
||||||
@ -793,13 +782,17 @@ pub(crate) struct ResponseParts {
|
|||||||
|
|
||||||
impl InnerResponse {
|
impl InnerResponse {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(status: StatusCode, body: Body) -> InnerResponse {
|
fn new(status: StatusCode, body: Body, pool: &'static ResponsePool) -> InnerResponse {
|
||||||
InnerResponse {
|
InnerResponse {
|
||||||
|
head: ResponseHead {
|
||||||
status,
|
status,
|
||||||
body,
|
|
||||||
version: None,
|
version: None,
|
||||||
headers: HeaderMap::with_capacity(16),
|
headers: HeaderMap::with_capacity(16),
|
||||||
reason: None,
|
reason: None,
|
||||||
|
flags: MessageFlags::empty(),
|
||||||
|
},
|
||||||
|
body,
|
||||||
|
pool,
|
||||||
chunked: None,
|
chunked: None,
|
||||||
encoding: None,
|
encoding: None,
|
||||||
connection_type: None,
|
connection_type: None,
|
||||||
@ -822,10 +815,7 @@ impl InnerResponse {
|
|||||||
|
|
||||||
ResponseParts {
|
ResponseParts {
|
||||||
body,
|
body,
|
||||||
version: self.version,
|
head: self.head,
|
||||||
headers: self.headers,
|
|
||||||
status: self.status,
|
|
||||||
reason: self.reason,
|
|
||||||
encoding: self.encoding,
|
encoding: self.encoding,
|
||||||
connection_type: self.connection_type,
|
connection_type: self.connection_type,
|
||||||
error: self.error,
|
error: self.error,
|
||||||
@ -841,16 +831,14 @@ impl InnerResponse {
|
|||||||
|
|
||||||
InnerResponse {
|
InnerResponse {
|
||||||
body,
|
body,
|
||||||
status: parts.status,
|
head: parts.head,
|
||||||
version: parts.version,
|
|
||||||
headers: parts.headers,
|
|
||||||
reason: parts.reason,
|
|
||||||
chunked: None,
|
chunked: None,
|
||||||
encoding: parts.encoding,
|
encoding: parts.encoding,
|
||||||
connection_type: parts.connection_type,
|
connection_type: parts.connection_type,
|
||||||
response_size: 0,
|
response_size: 0,
|
||||||
write_capacity: MAX_WRITE_BUFFER_SIZE,
|
write_capacity: MAX_WRITE_BUFFER_SIZE,
|
||||||
error: parts.error,
|
error: parts.error,
|
||||||
|
pool: ResponsePool::pool(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -876,17 +864,15 @@ impl ResponsePool {
|
|||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
) -> ResponseBuilder {
|
) -> ResponseBuilder {
|
||||||
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
||||||
msg.status = status;
|
msg.head.status = status;
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
pool,
|
|
||||||
response: Some(msg),
|
response: Some(msg),
|
||||||
err: None,
|
err: None,
|
||||||
cookies: None,
|
cookies: None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let msg = Box::new(InnerResponse::new(status, Body::Empty));
|
let msg = Box::new(InnerResponse::new(status, Body::Empty, pool));
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
pool,
|
|
||||||
response: Some(msg),
|
response: Some(msg),
|
||||||
err: None,
|
err: None,
|
||||||
cookies: None,
|
cookies: None,
|
||||||
@ -901,12 +887,11 @@ impl ResponsePool {
|
|||||||
body: Body,
|
body: Body,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
||||||
msg.status = status;
|
msg.head.status = status;
|
||||||
msg.body = body;
|
msg.body = body;
|
||||||
Response(msg, pool)
|
Response(msg)
|
||||||
} else {
|
} else {
|
||||||
let msg = Box::new(InnerResponse::new(status, body));
|
Response(Box::new(InnerResponse::new(status, body, pool)))
|
||||||
Response(msg, pool)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,13 +906,11 @@ impl ResponsePool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn release(&self, mut inner: Box<InnerResponse>) {
|
fn release(mut inner: Box<InnerResponse>) {
|
||||||
let mut p = self.0.borrow_mut();
|
let mut p = inner.pool.0.borrow_mut();
|
||||||
if p.len() < 128 {
|
if p.len() < 128 {
|
||||||
inner.headers.clear();
|
inner.head.clear();
|
||||||
inner.version = None;
|
|
||||||
inner.chunked = None;
|
inner.chunked = None;
|
||||||
inner.reason = None;
|
|
||||||
inner.encoding = None;
|
inner.encoding = None;
|
||||||
inner.connection_type = None;
|
inner.connection_type = None;
|
||||||
inner.response_size = 0;
|
inner.response_size = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user