mirror of
https://github.com/actix/actix-extras.git
synced 2025-01-23 15:24:36 +01:00
simplify Message api
This commit is contained in:
parent
a7a2d4cf5c
commit
b0e36fdcf9
@ -115,10 +115,10 @@ impl Decoder for Codec {
|
|||||||
None => None,
|
None => None,
|
||||||
})
|
})
|
||||||
} else if let Some((req, payload)) = self.decoder.decode(src)? {
|
} else if let Some((req, payload)) = self.decoder.decode(src)? {
|
||||||
self.flags
|
let head = req.head();
|
||||||
.set(Flags::HEAD, req.inner.head.method == Method::HEAD);
|
self.flags.set(Flags::HEAD, head.method == Method::HEAD);
|
||||||
self.version = req.inner().head.version;
|
self.version = head.version;
|
||||||
self.ctype = req.inner().head.connection_type();
|
self.ctype = head.connection_type();
|
||||||
if self.ctype == ConnectionType::KeepAlive
|
if self.ctype == ConnectionType::KeepAlive
|
||||||
&& !self.flags.contains(Flags::KEEPALIVE_ENABLED)
|
&& !self.flags.contains(Flags::KEEPALIVE_ENABLED)
|
||||||
{
|
{
|
||||||
|
@ -159,7 +159,7 @@ pub(crate) trait MessageType: Sized {
|
|||||||
|
|
||||||
impl MessageType for Request {
|
impl MessageType for Request {
|
||||||
fn set_connection_type(&mut self, ctype: Option<ConnectionType>) {
|
fn set_connection_type(&mut self, ctype: Option<ConnectionType>) {
|
||||||
self.inner_mut().head.ctype = ctype;
|
self.head_mut().ctype = ctype;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headers_mut(&mut self) -> &mut HeaderMap {
|
fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
@ -218,12 +218,10 @@ impl MessageType for Request {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
let head = msg.head_mut();
|
||||||
let inner = msg.inner_mut();
|
head.uri = uri;
|
||||||
inner.head.uri = uri;
|
head.method = method;
|
||||||
inner.head.method = method;
|
head.version = ver;
|
||||||
inner.head.version = ver;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some((msg, decoder)))
|
Ok(Some((msg, decoder)))
|
||||||
}
|
}
|
||||||
@ -817,7 +815,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Close));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Close));
|
||||||
|
|
||||||
let mut buf = BytesMut::from(
|
let mut buf = BytesMut::from(
|
||||||
"GET /test HTTP/1.1\r\n\
|
"GET /test HTTP/1.1\r\n\
|
||||||
@ -825,7 +823,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Close));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Close));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -836,7 +834,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Close));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Close));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -847,7 +845,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::KeepAlive));
|
assert_eq!(req.head().ctype, Some(ConnectionType::KeepAlive));
|
||||||
|
|
||||||
let mut buf = BytesMut::from(
|
let mut buf = BytesMut::from(
|
||||||
"GET /test HTTP/1.0\r\n\
|
"GET /test HTTP/1.0\r\n\
|
||||||
@ -855,7 +853,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::KeepAlive));
|
assert_eq!(req.head().ctype, Some(ConnectionType::KeepAlive));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -866,7 +864,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::KeepAlive));
|
assert_eq!(req.head().ctype, Some(ConnectionType::KeepAlive));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -877,7 +875,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.connection_type(), ConnectionType::Close);
|
assert_eq!(req.head().connection_type(), ConnectionType::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -888,11 +886,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert_eq!(req.inner().head.ctype, None);
|
assert_eq!(req.head().ctype, None);
|
||||||
assert_eq!(
|
assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
|
||||||
req.inner().head.connection_type(),
|
|
||||||
ConnectionType::KeepAlive
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -905,7 +900,7 @@ mod tests {
|
|||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert!(req.upgrade());
|
assert!(req.upgrade());
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Upgrade));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Upgrade));
|
||||||
|
|
||||||
let mut buf = BytesMut::from(
|
let mut buf = BytesMut::from(
|
||||||
"GET /test HTTP/1.1\r\n\
|
"GET /test HTTP/1.1\r\n\
|
||||||
@ -915,7 +910,7 @@ mod tests {
|
|||||||
let req = parse_ready!(&mut buf);
|
let req = parse_ready!(&mut buf);
|
||||||
|
|
||||||
assert!(req.upgrade());
|
assert!(req.upgrade());
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Upgrade));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Upgrade));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1013,7 +1008,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let mut reader = MessageDecoder::<Request>::default();
|
let mut reader = MessageDecoder::<Request>::default();
|
||||||
let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
|
let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
|
||||||
assert_eq!(req.inner().head.ctype, Some(ConnectionType::Upgrade));
|
assert_eq!(req.head().ctype, Some(ConnectionType::Upgrade));
|
||||||
assert!(req.upgrade());
|
assert!(req.upgrade());
|
||||||
assert!(pl.is_unhandled());
|
assert!(pl.is_unhandled());
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ where
|
|||||||
let (parts, body) = req.into_parts();
|
let (parts, body) = req.into_parts();
|
||||||
let mut req = Request::with_payload(body.into());
|
let mut req = Request::with_payload(body.into());
|
||||||
|
|
||||||
let head = &mut req.inner_mut().head;
|
let head = &mut req.head_mut();
|
||||||
head.uri = parts.uri;
|
head.uri = parts.uri;
|
||||||
head.method = parts.method;
|
head.method = parts.method;
|
||||||
head.version = parts.version;
|
head.version = parts.version;
|
||||||
|
104
src/message.rs
104
src/message.rs
@ -1,4 +1,4 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -146,12 +146,59 @@ impl ResponseHead {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Message<T: Head> {
|
pub struct Message<T: Head> {
|
||||||
pub head: T,
|
inner: Rc<MessageInner<T>>,
|
||||||
pub extensions: RefCell<Extensions>,
|
pool: &'static MessagePool<T>,
|
||||||
pub(crate) pool: &'static MessagePool<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Head> Message<T> {
|
impl<T: Head> Message<T> {
|
||||||
|
/// Get new message from the pool of objects
|
||||||
|
pub fn new() -> Self {
|
||||||
|
T::pool().get_message()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Message extensions
|
||||||
|
#[inline]
|
||||||
|
pub fn extensions(&self) -> Ref<Extensions> {
|
||||||
|
self.inner.as_ref().extensions.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutable reference to a the message's extensions
|
||||||
|
#[inline]
|
||||||
|
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||||
|
self.inner.as_ref().extensions.borrow_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Head> std::ops::Deref for Message<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner.as_ref().head
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Head> std::ops::DerefMut for Message<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut Rc::get_mut(&mut self.inner)
|
||||||
|
.expect("Multiple copies exist")
|
||||||
|
.head
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Head> Drop for Message<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if Rc::strong_count(&self.inner) == 1 {
|
||||||
|
self.pool.release(self.inner.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MessageInner<T: Head> {
|
||||||
|
head: T,
|
||||||
|
extensions: RefCell<Extensions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Head> MessageInner<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Reset request instance
|
/// Reset request instance
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
@ -160,10 +207,9 @@ impl<T: Head> Message<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Head> Default for Message<T> {
|
impl<T: Head> Default for MessageInner<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Message {
|
MessageInner {
|
||||||
pool: T::pool(),
|
|
||||||
head: T::default(),
|
head: T::default(),
|
||||||
extensions: RefCell::new(Extensions::new()),
|
extensions: RefCell::new(Extensions::new()),
|
||||||
}
|
}
|
||||||
@ -172,41 +218,39 @@ impl<T: Head> Default for Message<T> {
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Request's objects pool
|
/// Request's objects pool
|
||||||
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<Message<T>>>>);
|
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<MessageInner<T>>>>);
|
||||||
|
|
||||||
thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
|
thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
|
||||||
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());
|
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());
|
||||||
|
|
||||||
impl MessagePool<RequestHead> {
|
|
||||||
/// Get default request's pool
|
|
||||||
pub fn pool() -> &'static MessagePool<RequestHead> {
|
|
||||||
REQUEST_POOL.with(|p| *p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get Request object
|
|
||||||
#[inline]
|
|
||||||
pub fn get_message() -> Rc<Message<RequestHead>> {
|
|
||||||
REQUEST_POOL.with(|pool| {
|
|
||||||
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
|
||||||
if let Some(r) = Rc::get_mut(&mut msg) {
|
|
||||||
r.reset();
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
Rc::new(Message::default())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Head> MessagePool<T> {
|
impl<T: Head> MessagePool<T> {
|
||||||
fn create() -> &'static MessagePool<T> {
|
fn create() -> &'static MessagePool<T> {
|
||||||
let pool = MessagePool(RefCell::new(VecDeque::with_capacity(128)));
|
let pool = MessagePool(RefCell::new(VecDeque::with_capacity(128)));
|
||||||
Box::leak(Box::new(pool))
|
Box::leak(Box::new(pool))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get message from the pool
|
||||||
|
#[inline]
|
||||||
|
fn get_message(&'static self) -> Message<T> {
|
||||||
|
if let Some(mut msg) = self.0.borrow_mut().pop_front() {
|
||||||
|
if let Some(r) = Rc::get_mut(&mut msg) {
|
||||||
|
r.reset();
|
||||||
|
}
|
||||||
|
Message {
|
||||||
|
inner: msg,
|
||||||
|
pool: self,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Message {
|
||||||
|
inner: Rc::new(MessageInner::default()),
|
||||||
|
pool: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Release request instance
|
/// Release request instance
|
||||||
pub(crate) fn release(&self, msg: Rc<Message<T>>) {
|
fn release(&self, msg: Rc<MessageInner<T>>) {
|
||||||
let v = &mut self.0.borrow_mut();
|
let v = &mut self.0.borrow_mut();
|
||||||
if v.len() < 128 {
|
if v.len() < 128 {
|
||||||
v.push_front(msg);
|
v.push_front(msg);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
@ -9,13 +8,13 @@ use http::{header, HeaderMap, Method, Uri, Version};
|
|||||||
use crate::error::PayloadError;
|
use crate::error::PayloadError;
|
||||||
use crate::extensions::Extensions;
|
use crate::extensions::Extensions;
|
||||||
use crate::httpmessage::HttpMessage;
|
use crate::httpmessage::HttpMessage;
|
||||||
use crate::message::{Message, MessagePool, RequestHead};
|
use crate::message::{Message, RequestHead};
|
||||||
use crate::payload::Payload;
|
use crate::payload::Payload;
|
||||||
|
|
||||||
/// Request
|
/// Request
|
||||||
pub struct Request<P = Payload> {
|
pub struct Request<P = Payload> {
|
||||||
pub(crate) payload: RefCell<Option<P>>,
|
pub(crate) payload: RefCell<Option<P>>,
|
||||||
pub(crate) inner: Rc<Message<RequestHead>>,
|
pub(crate) inner: Message<RequestHead>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> HttpMessage for Request<P>
|
impl<P> HttpMessage for Request<P>
|
||||||
@ -25,7 +24,7 @@ where
|
|||||||
type Stream = P;
|
type Stream = P;
|
||||||
|
|
||||||
fn headers(&self) -> &HeaderMap {
|
fn headers(&self) -> &HeaderMap {
|
||||||
&self.inner.head.headers
|
&self.head().headers
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -34,12 +33,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Payload> From<Message<RequestHead>> for Request<Payload> {
|
||||||
|
fn from(msg: Message<RequestHead>) -> Self {
|
||||||
|
Request {
|
||||||
|
payload: RefCell::new(None),
|
||||||
|
inner: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Request<Payload> {
|
impl Request<Payload> {
|
||||||
/// Create new Request instance
|
/// Create new Request instance
|
||||||
pub fn new() -> Request<Payload> {
|
pub fn new() -> Request<Payload> {
|
||||||
Request {
|
Request {
|
||||||
payload: RefCell::new(None),
|
payload: RefCell::new(None),
|
||||||
inner: MessagePool::get_message(),
|
inner: Message::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +57,7 @@ impl<Payload> Request<Payload> {
|
|||||||
pub fn with_payload(payload: Payload) -> Request<Payload> {
|
pub fn with_payload(payload: Payload) -> Request<Payload> {
|
||||||
Request {
|
Request {
|
||||||
payload: RefCell::new(Some(payload.into())),
|
payload: RefCell::new(Some(payload.into())),
|
||||||
inner: MessagePool::get_message(),
|
inner: Message::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,123 +68,90 @@ impl<Payload> Request<Payload> {
|
|||||||
{
|
{
|
||||||
Request {
|
Request {
|
||||||
payload: RefCell::new(Some(payload.into())),
|
payload: RefCell::new(Some(payload.into())),
|
||||||
inner: self.inner.clone(),
|
inner: self.inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take request's payload
|
/// Split request into request head and payload
|
||||||
pub fn take_payload(mut self) -> (Option<Payload>, Request<()>) {
|
pub fn into_parts(mut self) -> (Message<RequestHead>, Option<Payload>) {
|
||||||
(
|
(self.inner, self.payload.get_mut().take())
|
||||||
self.payload.get_mut().take(),
|
|
||||||
Request {
|
|
||||||
payload: RefCell::new(None),
|
|
||||||
inner: self.inner.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// /// Create new Request instance with pool
|
|
||||||
// pub(crate) fn with_pool(pool: &'static MessagePool) -> Request {
|
|
||||||
// Request {
|
|
||||||
// inner: Rc::new(Message {
|
|
||||||
// pool,
|
|
||||||
// url: Url::default(),
|
|
||||||
// head: RequestHead::default(),
|
|
||||||
// status: StatusCode::OK,
|
|
||||||
// flags: Cell::new(MessageFlags::empty()),
|
|
||||||
// payload: RefCell::new(None),
|
|
||||||
// extensions: RefCell::new(Extensions::new()),
|
|
||||||
// }),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn inner(&self) -> &Message<RequestHead> {
|
|
||||||
self.inner.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn inner_mut(&mut self) -> &mut Message<RequestHead> {
|
|
||||||
Rc::get_mut(&mut self.inner).expect("Multiple copies exist")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Http message part of the request
|
/// Http message part of the request
|
||||||
pub fn head(&self) -> &RequestHead {
|
pub fn head(&self) -> &RequestHead {
|
||||||
&self.inner.as_ref().head
|
&*self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Mutable reference to a http message part of the request
|
/// Mutable reference to a http message part of the request
|
||||||
pub fn head_mut(&mut self) -> &mut RequestHead {
|
pub fn head_mut(&mut self) -> &mut RequestHead {
|
||||||
&mut self.inner_mut().head
|
&mut *self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request's uri.
|
/// Request's uri.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn uri(&self) -> &Uri {
|
pub fn uri(&self) -> &Uri {
|
||||||
&self.inner().head.uri
|
&self.head().uri
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable reference to the request's uri.
|
/// Mutable reference to the request's uri.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn uri_mut(&mut self) -> &mut Uri {
|
pub fn uri_mut(&mut self) -> &mut Uri {
|
||||||
&mut self.inner_mut().head.uri
|
&mut self.head_mut().uri
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the Request method.
|
/// Read the Request method.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn method(&self) -> &Method {
|
pub fn method(&self) -> &Method {
|
||||||
&self.inner().head.method
|
&self.head().method
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the Request Version.
|
/// Read the Request Version.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn version(&self) -> Version {
|
pub fn version(&self) -> Version {
|
||||||
self.inner().head.version
|
self.head().version
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The target path of this Request.
|
/// The target path of this Request.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn path(&self) -> &str {
|
pub fn path(&self) -> &str {
|
||||||
self.inner().head.uri.path()
|
self.head().uri.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns Request's headers.
|
/// Returns Request's headers.
|
||||||
pub fn headers(&self) -> &HeaderMap {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
&self.inner().head.headers
|
&self.head().headers
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns mutable Request's headers.
|
/// Returns mutable Request's headers.
|
||||||
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
&mut self.inner_mut().head.headers
|
&mut self.head_mut().headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request extensions
|
/// Request extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extensions(&self) -> Ref<Extensions> {
|
pub fn extensions(&self) -> Ref<Extensions> {
|
||||||
self.inner().extensions.borrow()
|
self.inner.extensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable reference to a the request's extensions
|
/// Mutable reference to a the request's extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||||
self.inner().extensions.borrow_mut()
|
self.inner.extensions_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if request requires connection upgrade
|
/// Check if request requires connection upgrade
|
||||||
pub fn upgrade(&self) -> bool {
|
pub fn upgrade(&self) -> bool {
|
||||||
if let Some(conn) = self.inner().head.headers.get(header::CONNECTION) {
|
if let Some(conn) = self.head().headers.get(header::CONNECTION) {
|
||||||
if let Ok(s) = conn.to_str() {
|
if let Ok(s) = conn.to_str() {
|
||||||
return s.to_lowercase().contains("upgrade");
|
return s.to_lowercase().contains("upgrade");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.inner().head.method == Method::CONNECT
|
self.head().method == Method::CONNECT
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[doc(hidden)]
|
// #[doc(hidden)]
|
||||||
@ -189,14 +164,6 @@ impl<Payload> Request<Payload> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Payload> Drop for Request<Payload> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if Rc::strong_count(&self.inner) == 1 {
|
|
||||||
self.inner.pool.release(self.inner.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Payload> fmt::Debug for Request<Payload> {
|
impl<Payload> fmt::Debug for Request<Payload> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
writeln!(
|
writeln!(
|
||||||
|
321
src/response.rs
321
src/response.rs
@ -1,7 +1,4 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
//! Http response
|
//! Http response
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::{fmt, str};
|
use std::{fmt, str};
|
||||||
|
|
||||||
@ -9,26 +6,27 @@ use bytes::{BufMut, Bytes, BytesMut};
|
|||||||
use cookie::{Cookie, CookieJar};
|
use cookie::{Cookie, CookieJar};
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
use http::{Error as HttpError, HeaderMap, HttpTryFrom, StatusCode, Version};
|
use http::{Error as HttpError, HeaderMap, HttpTryFrom, StatusCode};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
|
use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::header::{Header, IntoHeaderValue};
|
use crate::header::{Header, IntoHeaderValue};
|
||||||
use crate::message::{ConnectionType, Head, ResponseHead};
|
use crate::message::{ConnectionType, Head, Message, ResponseHead};
|
||||||
|
|
||||||
/// max write buffer size 64k
|
|
||||||
pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536;
|
|
||||||
|
|
||||||
/// An HTTP Response
|
/// An HTTP Response
|
||||||
pub struct Response<B: MessageBody = Body>(Box<InnerResponse>, ResponseBody<B>);
|
pub struct Response<B: MessageBody = Body> {
|
||||||
|
head: Message<ResponseHead>,
|
||||||
|
body: ResponseBody<B>,
|
||||||
|
error: Option<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Response<Body> {
|
impl Response<Body> {
|
||||||
/// Create http response builder with specific status.
|
/// Create http response builder with specific status.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build(status: StatusCode) -> ResponseBuilder {
|
pub fn build(status: StatusCode) -> ResponseBuilder {
|
||||||
ResponsePool::get(status)
|
ResponseBuilder::new(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create http response builder
|
/// Create http response builder
|
||||||
@ -40,14 +38,21 @@ impl Response<Body> {
|
|||||||
/// Constructs a response
|
/// Constructs a response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(status: StatusCode) -> Response {
|
pub fn new(status: StatusCode) -> Response {
|
||||||
ResponsePool::with_body(status, Body::Empty)
|
let mut head: Message<ResponseHead> = Message::new();
|
||||||
|
head.status = status;
|
||||||
|
|
||||||
|
Response {
|
||||||
|
head,
|
||||||
|
body: ResponseBody::Body(Body::Empty),
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs an error response
|
/// Constructs an error response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_error(error: Error) -> Response {
|
pub fn from_error(error: Error) -> Response {
|
||||||
let mut resp = error.as_response_error().error_response();
|
let mut resp = error.as_response_error().error_response();
|
||||||
resp.get_mut().error = Some(error);
|
resp.error = Some(error);
|
||||||
resp
|
resp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +72,7 @@ impl Response<Body> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
response: Some(self.0),
|
head: Some(self.head),
|
||||||
err: None,
|
err: None,
|
||||||
cookies: jar,
|
cookies: jar,
|
||||||
}
|
}
|
||||||
@ -75,90 +80,85 @@ impl Response<Body> {
|
|||||||
|
|
||||||
/// Convert response to response with body
|
/// Convert response to response with body
|
||||||
pub fn into_body<B: MessageBody>(self) -> Response<B> {
|
pub fn into_body<B: MessageBody>(self) -> Response<B> {
|
||||||
let b = match self.1 {
|
let b = match self.body {
|
||||||
ResponseBody::Body(b) => b,
|
ResponseBody::Body(b) => b,
|
||||||
ResponseBody::Other(b) => b,
|
ResponseBody::Other(b) => b,
|
||||||
};
|
};
|
||||||
Response(self.0, ResponseBody::Other(b))
|
Response {
|
||||||
|
head: self.head,
|
||||||
|
error: self.error,
|
||||||
|
body: ResponseBody::Other(b),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBody> Response<B> {
|
impl<B: MessageBody> Response<B> {
|
||||||
#[inline]
|
|
||||||
fn get_ref(&self) -> &InnerResponse {
|
|
||||||
self.0.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_mut(&mut self) -> &mut InnerResponse {
|
|
||||||
self.0.as_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Http message part of the response
|
/// Http message part of the response
|
||||||
pub fn head(&self) -> &ResponseHead {
|
pub fn head(&self) -> &ResponseHead {
|
||||||
&self.0.as_ref().head
|
&*self.head
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Mutable reference to a http message part of the response
|
/// Mutable reference to a http message part of the response
|
||||||
pub fn head_mut(&mut self) -> &mut ResponseHead {
|
pub fn head_mut(&mut self) -> &mut ResponseHead {
|
||||||
&mut self.0.as_mut().head
|
&mut *self.head
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a response with body
|
/// Constructs a response with body
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_body(status: StatusCode, body: B) -> Response<B> {
|
pub fn with_body(status: StatusCode, body: B) -> Response<B> {
|
||||||
ResponsePool::with_body(status, body)
|
let mut head: Message<ResponseHead> = Message::new();
|
||||||
|
head.status = status;
|
||||||
|
Response {
|
||||||
|
head,
|
||||||
|
body: ResponseBody::Body(body),
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The source `error` for this response
|
/// The source `error` for this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn error(&self) -> Option<&Error> {
|
pub fn error(&self) -> Option<&Error> {
|
||||||
self.get_ref().error.as_ref()
|
self.error.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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().head.status
|
self.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().head.status
|
&mut self.head.status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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().head.headers
|
&self.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().head.headers
|
&mut self.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
|
iter: self.head.headers.get_all(header::SET_COOKIE).iter(),
|
||||||
.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().head.headers;
|
let h = &mut self.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);
|
||||||
@ -170,7 +170,7 @@ impl<B: MessageBody> Response<B> {
|
|||||||
/// 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().head.headers;
|
let h = &mut self.head.headers;
|
||||||
let vals: Vec<HeaderValue> = h
|
let vals: Vec<HeaderValue> = h
|
||||||
.get_all(header::SET_COOKIE)
|
.get_all(header::SET_COOKIE)
|
||||||
.iter()
|
.iter()
|
||||||
@ -196,28 +196,36 @@ impl<B: MessageBody> Response<B> {
|
|||||||
/// Connection upgrade status
|
/// Connection upgrade status
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn upgrade(&self) -> bool {
|
pub fn upgrade(&self) -> bool {
|
||||||
self.get_ref().head.upgrade()
|
self.head.upgrade()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Keep-alive status for this connection
|
/// Keep-alive status for this connection
|
||||||
pub fn keep_alive(&self) -> bool {
|
pub fn keep_alive(&self) -> bool {
|
||||||
self.get_ref().head.keep_alive()
|
self.head.keep_alive()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get body os this response
|
/// Get body os this response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn body(&self) -> &ResponseBody<B> {
|
pub fn body(&self) -> &ResponseBody<B> {
|
||||||
&self.1
|
&self.body
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body
|
/// Set a body
|
||||||
pub(crate) fn set_body<B2: MessageBody>(self, body: B2) -> Response<B2> {
|
pub(crate) fn set_body<B2: MessageBody>(self, body: B2) -> Response<B2> {
|
||||||
Response(self.0, ResponseBody::Body(body))
|
Response {
|
||||||
|
head: self.head,
|
||||||
|
body: ResponseBody::Body(body),
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drop request's body
|
/// Drop request's body
|
||||||
pub(crate) fn drop_body(self) -> Response<()> {
|
pub(crate) fn drop_body(self) -> Response<()> {
|
||||||
Response(self.0, ResponseBody::Body(()))
|
Response {
|
||||||
|
head: self.head,
|
||||||
|
body: ResponseBody::Body(()),
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body and return previous body value
|
/// Set a body and return previous body value
|
||||||
@ -225,21 +233,14 @@ impl<B: MessageBody> Response<B> {
|
|||||||
self,
|
self,
|
||||||
body: B2,
|
body: B2,
|
||||||
) -> (Response<B2>, ResponseBody<B>) {
|
) -> (Response<B2>, ResponseBody<B>) {
|
||||||
(Response(self.0, ResponseBody::Body(body)), self.1)
|
(
|
||||||
}
|
Response {
|
||||||
|
head: self.head,
|
||||||
/// Size of response in bytes, excluding HTTP headers
|
body: ResponseBody::Body(body),
|
||||||
pub fn response_size(&self) -> u64 {
|
error: self.error,
|
||||||
self.get_ref().response_size
|
},
|
||||||
}
|
self.body,
|
||||||
|
)
|
||||||
/// Set response size
|
|
||||||
pub(crate) fn set_response_size(&mut self, size: u64) {
|
|
||||||
self.get_mut().response_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn release(self) {
|
|
||||||
ResponsePool::release(self.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,15 +249,15 @@ impl<B: MessageBody> fmt::Debug for Response<B> {
|
|||||||
let res = writeln!(
|
let res = writeln!(
|
||||||
f,
|
f,
|
||||||
"\nResponse {:?} {}{}",
|
"\nResponse {:?} {}{}",
|
||||||
self.get_ref().head.version,
|
self.head.version,
|
||||||
self.get_ref().head.status,
|
self.head.status,
|
||||||
self.get_ref().head.reason.unwrap_or(""),
|
self.head.reason.unwrap_or(""),
|
||||||
);
|
);
|
||||||
let _ = writeln!(f, " headers:");
|
let _ = writeln!(f, " headers:");
|
||||||
for (key, val) in self.get_ref().head.headers.iter() {
|
for (key, val) in self.head.headers.iter() {
|
||||||
let _ = writeln!(f, " {:?}: {:?}", key, val);
|
let _ = writeln!(f, " {:?}: {:?}", key, val);
|
||||||
}
|
}
|
||||||
let _ = writeln!(f, " body: {:?}", self.1.length());
|
let _ = writeln!(f, " body: {:?}", self.body.length());
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,17 +285,29 @@ 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 {
|
||||||
response: Option<Box<InnerResponse>>,
|
head: Option<Message<ResponseHead>>,
|
||||||
err: Option<HttpError>,
|
err: Option<HttpError>,
|
||||||
cookies: Option<CookieJar>,
|
cookies: Option<CookieJar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseBuilder {
|
impl ResponseBuilder {
|
||||||
|
/// Create response builder
|
||||||
|
pub fn new(status: StatusCode) -> Self {
|
||||||
|
let mut head: Message<ResponseHead> = Message::new();
|
||||||
|
head.status = status;
|
||||||
|
|
||||||
|
ResponseBuilder {
|
||||||
|
head: Some(head),
|
||||||
|
err: None,
|
||||||
|
cookies: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set HTTP status code of this response.
|
/// Set HTTP status code of this response.
|
||||||
#[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.head, &self.err) {
|
||||||
parts.head.status = status;
|
parts.status = status;
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -316,10 +329,10 @@ impl ResponseBuilder {
|
|||||||
/// ```
|
/// ```
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn set<H: Header>(&mut self, hdr: H) -> &mut Self {
|
pub fn set<H: Header>(&mut self, hdr: H) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
match hdr.try_into() {
|
match hdr.try_into() {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.head.headers.append(H::name(), value);
|
parts.headers.append(H::name(), value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
}
|
}
|
||||||
@ -346,11 +359,11 @@ impl ResponseBuilder {
|
|||||||
HeaderName: HttpTryFrom<K>,
|
HeaderName: HttpTryFrom<K>,
|
||||||
V: IntoHeaderValue,
|
V: IntoHeaderValue,
|
||||||
{
|
{
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
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.head.headers.append(key, value);
|
parts.headers.append(key, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
},
|
},
|
||||||
@ -379,11 +392,11 @@ impl ResponseBuilder {
|
|||||||
HeaderName: HttpTryFrom<K>,
|
HeaderName: HttpTryFrom<K>,
|
||||||
V: IntoHeaderValue,
|
V: IntoHeaderValue,
|
||||||
{
|
{
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
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.head.headers.insert(key, value);
|
parts.headers.insert(key, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
},
|
},
|
||||||
@ -396,8 +409,8 @@ impl ResponseBuilder {
|
|||||||
/// Set the custom reason for the response.
|
/// Set the custom reason for the response.
|
||||||
#[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.head, &self.err) {
|
||||||
parts.head.reason = Some(reason);
|
parts.reason = Some(reason);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -405,8 +418,8 @@ impl ResponseBuilder {
|
|||||||
/// Set connection type to KeepAlive
|
/// Set connection type to KeepAlive
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn keep_alive(&mut self) -> &mut Self {
|
pub fn keep_alive(&mut self) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
parts.head.set_connection_type(ConnectionType::KeepAlive);
|
parts.set_connection_type(ConnectionType::KeepAlive);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -417,8 +430,8 @@ impl ResponseBuilder {
|
|||||||
where
|
where
|
||||||
V: IntoHeaderValue,
|
V: IntoHeaderValue,
|
||||||
{
|
{
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
parts.head.set_connection_type(ConnectionType::Upgrade);
|
parts.set_connection_type(ConnectionType::Upgrade);
|
||||||
}
|
}
|
||||||
self.set_header(header::UPGRADE, value)
|
self.set_header(header::UPGRADE, value)
|
||||||
}
|
}
|
||||||
@ -426,8 +439,8 @@ impl ResponseBuilder {
|
|||||||
/// Force close connection, even if it is marked as keep-alive
|
/// Force close connection, even if it is marked as keep-alive
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn force_close(&mut self) -> &mut Self {
|
pub fn force_close(&mut self) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
parts.head.set_connection_type(ConnectionType::Close);
|
parts.set_connection_type(ConnectionType::Close);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -438,10 +451,10 @@ impl ResponseBuilder {
|
|||||||
where
|
where
|
||||||
HeaderValue: HttpTryFrom<V>,
|
HeaderValue: HttpTryFrom<V>,
|
||||||
{
|
{
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.head, &self.err) {
|
||||||
match HeaderValue::try_from(value) {
|
match HeaderValue::try_from(value) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.head.headers.insert(header::CONTENT_TYPE, value);
|
parts.headers.insert(header::CONTENT_TYPE, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(e) => self.err = Some(e.into()),
|
||||||
};
|
};
|
||||||
@ -540,20 +553,6 @@ impl ResponseBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Set write buffer capacity
|
|
||||||
// ///
|
|
||||||
// /// This parameter makes sense only for streaming response
|
|
||||||
// /// or actor. If write buffer reaches specified capacity, stream or actor
|
|
||||||
// /// get paused.
|
|
||||||
// ///
|
|
||||||
// /// Default write buffer capacity is 64kb
|
|
||||||
// pub fn write_buffer_capacity(&mut self, cap: usize) -> &mut Self {
|
|
||||||
// if let Some(parts) = parts(&mut self.response, &self.err) {
|
|
||||||
// parts.write_capacity = cap;
|
|
||||||
// }
|
|
||||||
// self
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Set a body and generate `Response`.
|
/// Set a body and generate `Response`.
|
||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
@ -569,19 +568,23 @@ impl ResponseBuilder {
|
|||||||
return Response::from(Error::from(e)).into_body();
|
return Response::from(Error::from(e)).into_body();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut response = self.response.take().expect("cannot reuse response builder");
|
let mut response = self.head.take().expect("cannot reuse response builder");
|
||||||
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) => {
|
Ok(val) => {
|
||||||
let _ = response.head.headers.append(header::SET_COOKIE, val);
|
let _ = response.headers.append(header::SET_COOKIE, val);
|
||||||
}
|
}
|
||||||
Err(e) => return Response::from(Error::from(e)).into_body(),
|
Err(e) => return Response::from(Error::from(e)).into_body(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Response(response, ResponseBody::Body(body))
|
Response {
|
||||||
|
head: response,
|
||||||
|
body: ResponseBody::Body(body),
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -609,9 +612,8 @@ impl ResponseBuilder {
|
|||||||
pub fn json2<T: Serialize>(&mut self, value: &T) -> Response {
|
pub fn json2<T: Serialize>(&mut self, value: &T) -> Response {
|
||||||
match serde_json::to_string(value) {
|
match serde_json::to_string(value) {
|
||||||
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.head, &self.err) {
|
||||||
{
|
parts.headers.contains_key(header::CONTENT_TYPE)
|
||||||
parts.head.headers.contains_key(header::CONTENT_TYPE)
|
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
@ -636,7 +638,7 @@ 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 {
|
||||||
response: self.response.take(),
|
head: self.head.take(),
|
||||||
err: self.err.take(),
|
err: self.err.take(),
|
||||||
cookies: self.cookies.take(),
|
cookies: self.cookies.take(),
|
||||||
}
|
}
|
||||||
@ -646,9 +648,9 @@ impl ResponseBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::borrowed_box)]
|
#[allow(clippy::borrowed_box)]
|
||||||
fn parts<'a>(
|
fn parts<'a>(
|
||||||
parts: &'a mut Option<Box<InnerResponse>>,
|
parts: &'a mut Option<Message<ResponseHead>>,
|
||||||
err: &Option<HttpError>,
|
err: &Option<HttpError>,
|
||||||
) -> Option<&'a mut Box<InnerResponse>> {
|
) -> Option<&'a mut Message<ResponseHead>> {
|
||||||
if err.is_some() {
|
if err.is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -719,107 +721,6 @@ impl From<BytesMut> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InnerResponse {
|
|
||||||
head: ResponseHead,
|
|
||||||
response_size: u64,
|
|
||||||
error: Option<Error>,
|
|
||||||
pool: &'static ResponsePool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InnerResponse {
|
|
||||||
#[inline]
|
|
||||||
fn new(status: StatusCode, pool: &'static ResponsePool) -> InnerResponse {
|
|
||||||
InnerResponse {
|
|
||||||
head: ResponseHead {
|
|
||||||
status,
|
|
||||||
version: Version::default(),
|
|
||||||
headers: HeaderMap::with_capacity(16),
|
|
||||||
reason: None,
|
|
||||||
ctype: None,
|
|
||||||
},
|
|
||||||
pool,
|
|
||||||
response_size: 0,
|
|
||||||
error: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Internal use only!
|
|
||||||
pub(crate) struct ResponsePool(RefCell<VecDeque<Box<InnerResponse>>>);
|
|
||||||
|
|
||||||
thread_local!(static POOL: &'static ResponsePool = ResponsePool::pool());
|
|
||||||
|
|
||||||
impl ResponsePool {
|
|
||||||
fn pool() -> &'static ResponsePool {
|
|
||||||
let pool = ResponsePool(RefCell::new(VecDeque::with_capacity(128)));
|
|
||||||
Box::leak(Box::new(pool))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pool() -> &'static ResponsePool {
|
|
||||||
POOL.with(|p| *p)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_builder(
|
|
||||||
pool: &'static ResponsePool,
|
|
||||||
status: StatusCode,
|
|
||||||
) -> ResponseBuilder {
|
|
||||||
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
|
||||||
msg.head.status = status;
|
|
||||||
ResponseBuilder {
|
|
||||||
response: Some(msg),
|
|
||||||
err: None,
|
|
||||||
cookies: None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let msg = Box::new(InnerResponse::new(status, pool));
|
|
||||||
ResponseBuilder {
|
|
||||||
response: Some(msg),
|
|
||||||
err: None,
|
|
||||||
cookies: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_response<B: MessageBody>(
|
|
||||||
pool: &'static ResponsePool,
|
|
||||||
status: StatusCode,
|
|
||||||
body: B,
|
|
||||||
) -> Response<B> {
|
|
||||||
if let Some(mut msg) = pool.0.borrow_mut().pop_front() {
|
|
||||||
msg.head.status = status;
|
|
||||||
Response(msg, ResponseBody::Body(body))
|
|
||||||
} else {
|
|
||||||
Response(
|
|
||||||
Box::new(InnerResponse::new(status, pool)),
|
|
||||||
ResponseBody::Body(body),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get(status: StatusCode) -> ResponseBuilder {
|
|
||||||
POOL.with(|pool| ResponsePool::get_builder(pool, status))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn with_body<B: MessageBody>(status: StatusCode, body: B) -> Response<B> {
|
|
||||||
POOL.with(|pool| ResponsePool::get_response(pool, status, body))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn release(mut inner: Box<InnerResponse>) {
|
|
||||||
let mut p = inner.pool.0.borrow_mut();
|
|
||||||
if p.len() < 128 {
|
|
||||||
inner.head.clear();
|
|
||||||
inner.response_size = 0;
|
|
||||||
inner.error = None;
|
|
||||||
p.push_front(inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
10
src/test.rs
10
src/test.rs
@ -154,11 +154,11 @@ impl TestRequest {
|
|||||||
Request::with_payload(crate::h1::Payload::empty().into())
|
Request::with_payload(crate::h1::Payload::empty().into())
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner = req.inner_mut();
|
let head = req.head_mut();
|
||||||
inner.head.uri = uri;
|
head.uri = uri;
|
||||||
inner.head.method = method;
|
head.method = method;
|
||||||
inner.head.version = version;
|
head.version = version;
|
||||||
inner.head.headers = headers;
|
head.headers = headers;
|
||||||
|
|
||||||
// req.set_cookies(cookies);
|
// req.set_cookies(cookies);
|
||||||
req
|
req
|
||||||
|
Loading…
x
Reference in New Issue
Block a user