1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-07-01 16:55:08 +02:00

move response extensions out of head (#2585)

This commit is contained in:
Rob Ede
2022-01-19 02:09:25 +00:00
committed by GitHub
parent 7b8a392ef5
commit 2ffc21dd4f
21 changed files with 205 additions and 226 deletions

View File

@ -1,9 +1,6 @@
//! HTTP response builder.
use std::{
cell::{Ref, RefMut},
fmt, str,
};
use std::{cell::RefCell, fmt, str};
use crate::{
body::{EitherBody, MessageBody},
@ -202,20 +199,6 @@ impl ResponseBuilder {
self
}
/// Responses extensions
#[inline]
pub fn extensions(&self) -> Ref<'_, Extensions> {
let head = self.head.as_ref().expect("cannot reuse response builder");
head.extensions.borrow()
}
/// Mutable reference to a the response's extensions
#[inline]
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
let head = self.head.as_ref().expect("cannot reuse response builder");
head.extensions.borrow_mut()
}
/// Generate response with a wrapped body.
///
/// This `ResponseBuilder` will be left in a useless state.
@ -238,7 +221,12 @@ impl ResponseBuilder {
}
let head = self.head.take().expect("cannot reuse response builder");
Ok(Response { head, body })
Ok(Response {
head,
body,
extensions: RefCell::new(Extensions::new()),
})
}
/// Generate response with an empty body.

View File

@ -1,25 +1,19 @@
//! Response head type and caching pool.
use std::{
cell::{Ref, RefCell, RefMut},
ops,
};
use std::{cell::RefCell, ops};
use crate::{
header::HeaderMap, message::Flags, ConnectionType, Extensions, StatusCode, Version,
};
use crate::{header::HeaderMap, message::Flags, ConnectionType, StatusCode, Version};
thread_local! {
static RESPONSE_POOL: BoxedResponsePool = BoxedResponsePool::create();
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ResponseHead {
pub version: Version,
pub status: StatusCode,
pub headers: HeaderMap,
pub reason: Option<&'static str>,
pub(crate) extensions: RefCell<Extensions>,
pub(crate) flags: Flags,
}
@ -33,18 +27,17 @@ impl ResponseHead {
headers: HeaderMap::with_capacity(12),
reason: None,
flags: Flags::empty(),
extensions: RefCell::new(Extensions::new()),
}
}
#[inline]
/// Read the message headers.
#[inline]
pub fn headers(&self) -> &HeaderMap {
&self.headers
}
#[inline]
/// Mutable reference to the message headers.
#[inline]
pub fn headers_mut(&mut self) -> &mut HeaderMap {
&mut self.headers
}
@ -61,20 +54,8 @@ impl ResponseHead {
}
}
/// Message extensions
#[inline]
pub fn extensions(&self) -> Ref<'_, Extensions> {
self.extensions.borrow()
}
/// Mutable reference to a the message's extensions
#[inline]
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.extensions.borrow_mut()
}
#[inline]
/// Set connection type of the message
#[inline]
pub fn set_connection_type(&mut self, ctype: ConnectionType) {
match ctype {
ConnectionType::Close => self.flags.insert(Flags::CLOSE),
@ -133,14 +114,14 @@ impl ResponseHead {
}
}
#[inline]
/// Get response body chunking state
#[inline]
pub fn chunked(&self) -> bool {
!self.flags.contains(Flags::NO_CHUNKING)
}
#[inline]
/// Set no chunking for payload
#[inline]
pub fn no_chunking(&mut self, val: bool) {
if val {
self.flags.insert(Flags::NO_CHUNKING);
@ -183,7 +164,7 @@ impl Drop for BoxedResponseHead {
}
}
/// Request's objects pool
/// Response head object pool.
#[doc(hidden)]
pub struct BoxedResponsePool(#[allow(clippy::vec_box)] RefCell<Vec<Box<ResponseHead>>>);
@ -192,7 +173,7 @@ impl BoxedResponsePool {
BoxedResponsePool(RefCell::new(Vec::with_capacity(128)))
}
/// Get message from the pool
/// Get message from the pool.
#[inline]
fn get_message(&self, status: StatusCode) -> BoxedResponseHead {
if let Some(mut head) = self.0.borrow_mut().pop() {
@ -208,12 +189,12 @@ impl BoxedResponsePool {
}
}
/// Release request instance
/// Release request instance.
#[inline]
fn release(&self, mut msg: Box<ResponseHead>) {
fn release(&self, msg: Box<ResponseHead>) {
let pool = &mut self.0.borrow_mut();
if pool.len() < 128 {
msg.extensions.get_mut().clear();
pool.push(msg);
}
}

View File

@ -1,7 +1,7 @@
//! HTTP response.
use std::{
cell::{Ref, RefMut},
cell::{Ref, RefCell, RefMut},
fmt, str,
};
@ -9,7 +9,7 @@ use bytes::{Bytes, BytesMut};
use bytestring::ByteString;
use crate::{
body::{BoxBody, MessageBody},
body::{BoxBody, EitherBody, MessageBody},
header::{self, HeaderMap, TryIntoHeaderValue},
responses::BoxedResponseHead,
Error, Extensions, ResponseBuilder, ResponseHead, StatusCode,
@ -19,6 +19,7 @@ use crate::{
pub struct Response<B> {
pub(crate) head: BoxedResponseHead,
pub(crate) body: B,
pub(crate) extensions: RefCell<Extensions>,
}
impl Response<BoxBody> {
@ -28,6 +29,7 @@ impl Response<BoxBody> {
Response {
head: BoxedResponseHead::new(status),
body: BoxBody::new(()),
extensions: RefCell::new(Extensions::new()),
}
}
@ -74,6 +76,7 @@ impl<B> Response<B> {
Response {
head: BoxedResponseHead::new(status),
body,
extensions: RefCell::new(Extensions::new()),
}
}
@ -120,20 +123,21 @@ impl<B> Response<B> {
}
/// Returns true if keep-alive is enabled.
#[inline]
pub fn keep_alive(&self) -> bool {
self.head.keep_alive()
}
/// Returns a reference to the extensions of this response.
/// Returns a reference to the request-local data/extensions container.
#[inline]
pub fn extensions(&self) -> Ref<'_, Extensions> {
self.head.extensions.borrow()
self.extensions.borrow()
}
/// Returns a mutable reference to the extensions of this response.
/// Returns a mutable reference to the request-local data/extensions container.
#[inline]
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
self.head.extensions.borrow_mut()
self.extensions.borrow_mut()
}
/// Returns a reference to the body of this response.
@ -143,24 +147,29 @@ impl<B> Response<B> {
}
/// Sets new body.
#[inline]
pub fn set_body<B2>(self, body: B2) -> Response<B2> {
Response {
head: self.head,
body,
extensions: self.extensions,
}
}
/// Drops body and returns new response.
#[inline]
pub fn drop_body(self) -> Response<()> {
self.set_body(())
}
/// Sets new body, returning new response and previous body value.
#[inline]
pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, B) {
(
Response {
head: self.head,
body,
extensions: self.extensions,
},
self.body,
)
@ -171,11 +180,15 @@ impl<B> Response<B> {
/// # Implementation Notes
/// Due to internal performance optimizations, the first element of the returned tuple is a
/// `Response` as well but only contains the head of the response this was called on.
#[inline]
pub fn into_parts(self) -> (Response<()>, B) {
self.replace_body(())
}
/// Returns new response with mapped body.
/// Map the current body type to another using a closure. Returns a new response.
///
/// Closure receives the response head and the current body type.
#[inline]
pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
where
F: FnOnce(&mut ResponseHead, B) -> B2,
@ -185,6 +198,7 @@ impl<B> Response<B> {
Response {
head: self.head,
body,
extensions: self.extensions,
}
}
@ -197,6 +211,7 @@ impl<B> Response<B> {
}
/// Returns body, consuming this response.
#[inline]
pub fn into_body(self) -> B {
self.body
}
@ -239,9 +254,9 @@ impl<I: Into<Response<BoxBody>>, E: Into<Error>> From<Result<I, E>> for Response
}
}
impl From<ResponseBuilder> for Response<BoxBody> {
impl From<ResponseBuilder> for Response<EitherBody<()>> {
fn from(mut builder: ResponseBuilder) -> Self {
builder.finish().map_into_boxed_body()
builder.finish()
}
}