1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-12-01 02:54:36 +01:00
actix-web/actix-http/src/message.rs

491 lines
12 KiB
Rust
Raw Normal View History

use std::{
cell::{Ref, RefCell, RefMut},
net,
rc::Rc,
};
2018-11-17 04:28:07 +01:00
2019-03-27 18:38:01 +01:00
use bitflags::bitflags;
use crate::{
header::{self, HeaderMap},
Extensions, Method, StatusCode, Uri, Version,
};
2018-11-17 04:28:07 +01:00
/// Represents various types of connection
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ConnectionType {
/// Close connection after response
Close,
2021-02-12 01:15:25 +01:00
/// Keep connection alive after response
KeepAlive,
2021-02-12 01:15:25 +01:00
/// Connection is upgraded to different type
Upgrade,
}
2019-03-27 18:38:01 +01:00
bitflags! {
pub(crate) struct Flags: u8 {
const CLOSE = 0b0000_0001;
const KEEP_ALIVE = 0b0000_0010;
const UPGRADE = 0b0000_0100;
2019-04-06 01:46:44 +02:00
const EXPECT = 0b0000_1000;
const NO_CHUNKING = 0b0001_0000;
const CAMEL_CASE = 0b0010_0000;
2019-03-27 18:38:01 +01:00
}
}
2018-11-17 04:28:07 +01:00
#[doc(hidden)]
pub trait Head: Default + 'static {
fn clear(&mut self);
fn with_pool<F, R>(f: F) -> R
where
F: FnOnce(&MessagePool<Self>) -> R;
2018-11-17 04:28:07 +01:00
}
2018-11-19 23:57:12 +01:00
#[derive(Debug)]
2018-11-17 04:28:07 +01:00
pub struct RequestHead {
pub method: Method,
2021-12-04 20:40:47 +01:00
pub uri: Uri,
2018-11-17 04:28:07 +01:00
pub version: Version,
pub headers: HeaderMap,
2019-02-09 19:33:49 +01:00
pub extensions: RefCell<Extensions>,
pub peer_addr: Option<net::SocketAddr>,
2019-03-27 18:38:01 +01:00
flags: Flags,
2018-11-17 04:28:07 +01:00
}
impl Default for RequestHead {
fn default() -> RequestHead {
RequestHead {
method: Method::default(),
2021-12-04 20:40:47 +01:00
uri: Uri::default(),
2018-11-17 04:28:07 +01:00
version: Version::HTTP_11,
headers: HeaderMap::with_capacity(16),
2019-02-09 19:33:49 +01:00
extensions: RefCell::new(Extensions::new()),
2021-12-04 20:40:47 +01:00
peer_addr: None,
flags: Flags::empty(),
2018-11-17 04:28:07 +01:00
}
}
}
impl Head for RequestHead {
fn clear(&mut self) {
2019-03-27 18:38:01 +01:00
self.flags = Flags::empty();
2018-11-17 04:28:07 +01:00
self.headers.clear();
2021-01-04 14:03:46 +01:00
self.extensions.get_mut().clear();
2018-11-19 02:52:56 +01:00
}
fn with_pool<F, R>(f: F) -> R
where
F: FnOnce(&MessagePool<Self>) -> R,
{
REQUEST_POOL.with(|p| f(p))
2019-03-27 18:38:01 +01:00
}
}
impl RequestHead {
/// Message extensions
#[inline]
2019-12-07 19:46:51 +01:00
pub fn extensions(&self) -> Ref<'_, Extensions> {
2019-03-27 18:38:01 +01:00
self.extensions.borrow()
}
/// Mutable reference to a the message's extensions
#[inline]
2019-12-07 19:46:51 +01:00
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
2019-03-27 18:38:01 +01:00
self.extensions.borrow_mut()
}
/// Read the message headers.
pub fn headers(&self) -> &HeaderMap {
2019-02-13 22:52:11 +01:00
&self.headers
}
2019-03-27 18:38:01 +01:00
/// Mutable reference to the message headers.
pub fn headers_mut(&mut self) -> &mut HeaderMap {
2019-02-13 22:52:11 +01:00
&mut self.headers
}
/// Is to uppercase headers with Camel-Case.
2020-04-21 05:09:35 +02:00
/// Default is `false`
#[inline]
pub fn camel_case_headers(&self) -> bool {
self.flags.contains(Flags::CAMEL_CASE)
}
2020-04-21 05:09:35 +02:00
/// Set `true` to send headers which are formatted as Camel-Case.
#[inline]
pub fn set_camel_case_headers(&mut self, val: bool) {
if val {
self.flags.insert(Flags::CAMEL_CASE);
} else {
self.flags.remove(Flags::CAMEL_CASE);
}
}
2019-03-27 18:38:01 +01:00
#[inline]
/// Set connection type of the message
pub fn set_connection_type(&mut self, ctype: ConnectionType) {
match ctype {
ConnectionType::Close => self.flags.insert(Flags::CLOSE),
ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
}
2018-11-19 02:52:56 +01:00
}
2019-03-27 18:38:01 +01:00
#[inline]
/// Connection type
pub fn connection_type(&self) -> ConnectionType {
if self.flags.contains(Flags::CLOSE) {
ConnectionType::Close
} else if self.flags.contains(Flags::KEEP_ALIVE) {
ConnectionType::KeepAlive
} else if self.flags.contains(Flags::UPGRADE) {
ConnectionType::Upgrade
2018-11-19 23:57:12 +01:00
} else if self.version < Version::HTTP_11 {
ConnectionType::Close
2018-11-19 02:52:56 +01:00
} else {
ConnectionType::KeepAlive
2018-11-19 02:52:56 +01:00
}
}
2019-03-27 18:38:01 +01:00
/// Connection upgrade status
pub fn upgrade(&self) -> bool {
self.headers()
.get(header::CONNECTION)
.map(|hdr| {
if let Ok(s) = hdr.to_str() {
s.to_ascii_lowercase().contains("upgrade")
} else {
false
}
})
.unwrap_or(false)
2019-03-18 13:26:12 +01:00
}
2019-02-09 19:33:49 +01:00
#[inline]
2019-03-27 18:38:01 +01:00
/// Get response body chunking state
pub fn chunked(&self) -> bool {
!self.flags.contains(Flags::NO_CHUNKING)
2019-02-09 19:33:49 +01:00
}
#[inline]
2019-03-27 18:38:01 +01:00
pub fn no_chunking(&mut self, val: bool) {
if val {
self.flags.insert(Flags::NO_CHUNKING);
} else {
self.flags.remove(Flags::NO_CHUNKING);
}
2019-02-09 19:33:49 +01:00
}
2019-04-06 01:46:44 +02:00
#[inline]
/// Request contains `EXPECT` header
pub fn expect(&self) -> bool {
self.flags.contains(Flags::EXPECT)
}
#[inline]
pub(crate) fn set_expect(&mut self) {
self.flags.insert(Flags::EXPECT);
}
2019-02-09 19:33:49 +01:00
}
#[derive(Debug)]
2021-12-04 20:40:47 +01:00
#[allow(clippy::large_enum_variant)]
pub enum RequestHeadType {
Owned(RequestHead),
Rc(Rc<RequestHead>, Option<HeaderMap>),
}
impl RequestHeadType {
pub fn extra_headers(&self) -> Option<&HeaderMap> {
match self {
RequestHeadType::Owned(_) => None,
RequestHeadType::Rc(_, headers) => headers.as_ref(),
}
}
}
impl AsRef<RequestHead> for RequestHeadType {
fn as_ref(&self) -> &RequestHead {
match self {
2021-08-13 19:49:58 +02:00
RequestHeadType::Owned(head) => head,
RequestHeadType::Rc(head, _) => head.as_ref(),
}
}
}
impl From<RequestHead> for RequestHeadType {
fn from(head: RequestHead) -> Self {
RequestHeadType::Owned(head)
}
}
2018-11-19 23:57:12 +01:00
#[derive(Debug)]
2018-11-17 04:28:07 +01:00
pub struct ResponseHead {
pub version: Version,
2018-11-17 04:28:07 +01:00
pub status: StatusCode,
pub headers: HeaderMap,
pub reason: Option<&'static str>,
pub(crate) extensions: RefCell<Extensions>,
2019-03-27 18:38:01 +01:00
flags: Flags,
2018-11-17 04:28:07 +01:00
}
impl ResponseHead {
/// Create new instance of `ResponseHead` type
#[inline]
pub fn new(status: StatusCode) -> ResponseHead {
2018-11-17 04:28:07 +01:00
ResponseHead {
status,
version: Version::default(),
headers: HeaderMap::with_capacity(12),
2018-11-17 04:28:07 +01:00
reason: None,
2019-03-27 18:38:01 +01:00
flags: Flags::empty(),
extensions: RefCell::new(Extensions::new()),
2018-11-17 04:28:07 +01:00
}
}
/// Message extensions
#[inline]
2019-12-07 19:46:51 +01:00
pub fn extensions(&self) -> Ref<'_, Extensions> {
self.extensions.borrow()
}
/// Mutable reference to a the message's extensions
#[inline]
2019-12-07 19:46:51 +01:00
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.extensions.borrow_mut()
}
2019-03-27 18:38:01 +01:00
#[inline]
/// Read the message headers.
pub fn headers(&self) -> &HeaderMap {
2019-02-13 22:52:11 +01:00
&self.headers
}
2019-03-27 18:38:01 +01:00
#[inline]
/// Mutable reference to the message headers.
pub fn headers_mut(&mut self) -> &mut HeaderMap {
2019-02-13 22:52:11 +01:00
&mut self.headers
}
2019-03-27 18:38:01 +01:00
#[inline]
/// Set connection type of the message
pub fn set_connection_type(&mut self, ctype: ConnectionType) {
match ctype {
ConnectionType::Close => self.flags.insert(Flags::CLOSE),
ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
}
2018-11-19 02:52:56 +01:00
}
2019-03-27 18:38:01 +01:00
#[inline]
pub fn connection_type(&self) -> ConnectionType {
if self.flags.contains(Flags::CLOSE) {
ConnectionType::Close
} else if self.flags.contains(Flags::KEEP_ALIVE) {
ConnectionType::KeepAlive
} else if self.flags.contains(Flags::UPGRADE) {
ConnectionType::Upgrade
2018-11-19 23:57:12 +01:00
} else if self.version < Version::HTTP_11 {
ConnectionType::Close
2018-11-19 02:52:56 +01:00
} else {
ConnectionType::KeepAlive
2018-11-19 02:52:56 +01:00
}
}
2019-03-27 18:38:01 +01:00
/// Check if keep-alive is enabled
#[inline]
2019-03-27 18:38:01 +01:00
pub fn keep_alive(&self) -> bool {
self.connection_type() == ConnectionType::KeepAlive
2019-03-18 13:26:12 +01:00
}
2019-03-27 18:38:01 +01:00
/// Check upgrade status of this message
#[inline]
2019-03-27 18:38:01 +01:00
pub fn upgrade(&self) -> bool {
self.connection_type() == ConnectionType::Upgrade
2018-11-17 04:28:07 +01:00
}
2018-11-19 02:52:56 +01:00
/// Get custom reason for the response
#[inline]
pub fn reason(&self) -> &str {
self.reason.unwrap_or_else(|| {
2018-11-19 02:52:56 +01:00
self.status
.canonical_reason()
.unwrap_or("<unknown status code>")
})
2018-11-19 02:52:56 +01:00
}
2019-03-27 18:38:01 +01:00
#[inline]
pub(crate) fn conn_type(&self) -> Option<ConnectionType> {
2019-03-27 18:38:01 +01:00
if self.flags.contains(Flags::CLOSE) {
Some(ConnectionType::Close)
} else if self.flags.contains(Flags::KEEP_ALIVE) {
Some(ConnectionType::KeepAlive)
} else if self.flags.contains(Flags::UPGRADE) {
Some(ConnectionType::Upgrade)
} else {
None
}
}
#[inline]
/// Get response body chunking state
pub fn chunked(&self) -> bool {
!self.flags.contains(Flags::NO_CHUNKING)
}
#[inline]
/// Set no chunking for payload
pub fn no_chunking(&mut self, val: bool) {
if val {
self.flags.insert(Flags::NO_CHUNKING);
} else {
self.flags.remove(Flags::NO_CHUNKING);
}
}
2018-11-19 02:52:56 +01:00
}
2018-11-17 04:28:07 +01:00
pub struct Message<T: Head> {
/// Rc here should not be cloned by anyone.
/// It's used to reuse allocation of T and no shared ownership is allowed.
2019-02-09 19:33:49 +01:00
head: Rc<T>,
2018-11-17 04:28:07 +01:00
}
impl<T: Head> Message<T> {
2019-02-08 06:16:46 +01:00
/// Get new message from the pool of objects
pub fn new() -> Self {
T::with_pool(MessagePool::get_message)
2019-02-08 06:16:46 +01:00
}
}
impl<T: Head> std::ops::Deref for Message<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
2021-08-13 19:49:58 +02:00
self.head.as_ref()
2019-02-08 06:16:46 +01:00
}
}
impl<T: Head> std::ops::DerefMut for Message<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
2019-02-09 19:33:49 +01:00
Rc::get_mut(&mut self.head).expect("Multiple copies exist")
2019-02-08 06:16:46 +01:00
}
}
impl<T: Head> Drop for Message<T> {
fn drop(&mut self) {
2021-02-07 21:19:10 +01:00
T::with_pool(|p| p.release(self.head.clone()))
2018-11-17 04:28:07 +01:00
}
}
pub(crate) struct BoxedResponseHead {
head: Option<Box<ResponseHead>>,
}
impl BoxedResponseHead {
/// Get new message from the pool of objects
pub fn new(status: StatusCode) -> Self {
RESPONSE_POOL.with(|p| p.get_message(status))
}
}
impl std::ops::Deref for BoxedResponseHead {
type Target = ResponseHead;
fn deref(&self) -> &Self::Target {
self.head.as_ref().unwrap()
}
}
impl std::ops::DerefMut for BoxedResponseHead {
fn deref_mut(&mut self) -> &mut Self::Target {
self.head.as_mut().unwrap()
}
}
impl Drop for BoxedResponseHead {
fn drop(&mut self) {
2019-11-22 06:49:35 +01:00
if let Some(head) = self.head.take() {
RESPONSE_POOL.with(move |p| p.release(head))
}
}
}
2018-11-17 04:28:07 +01:00
#[doc(hidden)]
/// Request's objects pool
pub struct MessagePool<T: Head>(RefCell<Vec<Rc<T>>>);
2018-11-17 04:28:07 +01:00
#[doc(hidden)]
#[allow(clippy::vec_box)]
/// Request's objects pool
pub struct BoxedResponsePool(RefCell<Vec<Box<ResponseHead>>>);
thread_local!(static REQUEST_POOL: MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: BoxedResponsePool = BoxedResponsePool::create());
2018-11-17 04:28:07 +01:00
impl<T: Head> MessagePool<T> {
fn create() -> MessagePool<T> {
MessagePool(RefCell::new(Vec::with_capacity(128)))
2018-11-17 04:28:07 +01:00
}
2019-02-08 06:16:46 +01:00
/// Get message from the pool
#[inline]
fn get_message(&self) -> Message<T> {
if let Some(mut msg) = self.0.borrow_mut().pop() {
2021-01-04 14:03:46 +01:00
// Message is put in pool only when it's the last copy.
// which means it's guaranteed to be unique when popped out.
Rc::get_mut(&mut msg)
.expect("Multiple copies exist")
.clear();
Message { head: msg }
2019-02-08 06:16:46 +01:00
} else {
Message {
2019-02-09 19:33:49 +01:00
head: Rc::new(T::default()),
2019-02-08 06:16:46 +01:00
}
}
}
2018-11-17 04:28:07 +01:00
#[inline]
/// Release request instance
2019-02-09 19:33:49 +01:00
fn release(&self, msg: Rc<T>) {
2018-11-17 04:28:07 +01:00
let v = &mut self.0.borrow_mut();
if v.len() < 128 {
v.push(msg);
2018-11-17 04:28:07 +01:00
}
}
}
impl BoxedResponsePool {
fn create() -> BoxedResponsePool {
BoxedResponsePool(RefCell::new(Vec::with_capacity(128)))
}
/// Get message from the pool
#[inline]
fn get_message(&self, status: StatusCode) -> BoxedResponseHead {
if let Some(mut head) = self.0.borrow_mut().pop() {
head.reason = None;
head.status = status;
head.headers.clear();
head.flags = Flags::empty();
BoxedResponseHead { head: Some(head) }
} else {
BoxedResponseHead {
2021-01-07 22:55:00 +01:00
head: Some(Box::new(ResponseHead::new(status))),
}
}
}
#[inline]
/// Release request instance
2021-01-07 22:55:00 +01:00
fn release(&self, mut msg: Box<ResponseHead>) {
let v = &mut self.0.borrow_mut();
if v.len() < 128 {
2021-01-07 22:55:00 +01:00
msg.extensions.get_mut().clear();
v.push(msg);
}
}
}