use extensions nomenclature

This commit is contained in:
Rob Ede 2022-01-15 23:20:07 +00:00
parent 2fc9e76930
commit bb9d0e9cb9
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
11 changed files with 124 additions and 106 deletions

View File

@ -28,8 +28,6 @@ async fn main() -> io::Result<()> {
.insert_header(("x-head", HeaderValue::from_static("dummy value!"))) .insert_header(("x-head", HeaderValue::from_static("dummy value!")))
.body(body); .body(body);
res.req_data_mut().insert(5usize);
Ok::<_, Error>(res) Ok::<_, Error>(res)
}) })
// No TLS // No TLS

View File

@ -0,0 +1,53 @@
use std::{convert::Infallible, io};
use actix_http::{
body::EitherBody, HttpMessage as _, HttpService, Request, Response, StatusCode,
};
use actix_server::Server;
#[actix_rt::main]
async fn main() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
Server::build()
.bind("hello-world", ("127.0.0.1", 8080), || {
HttpService::build()
.client_timeout(1000)
.client_disconnect(1000)
.finish(|req: Request| async move {
let mut res = Response::build(StatusCode::OK).body("Hello world!");
match req.path() {
"/" => {}
"/ext" => {
res.extensions_mut().insert(123u8);
}
"/more" => {
res.extensions_mut().insert(123u8);
res.extensions_mut().insert(123u16);
res.extensions_mut().insert(123u32);
res.extensions_mut().insert(123u64);
res.extensions_mut().insert(123u128);
res.extensions_mut().insert(123i8);
res.extensions_mut().insert(123i16);
res.extensions_mut().insert(123i32);
res.extensions_mut().insert(123i64);
res.extensions_mut().insert(123i128);
}
_ => {
return Ok(Response::not_found()
.map_body(|_, body| EitherBody::right(body)))
}
}
Ok::<_, Infallible>(res)
})
.tcp()
})?
.workers(4)
.run()
.await
}

View File

@ -387,6 +387,7 @@ impl StdError for DispatchError {
/// A set of error that can occur during parsing content type. /// A set of error that can occur during parsing content type.
#[derive(Debug, Display, Error)] #[derive(Debug, Display, Error)]
#[cfg_attr(test, derive(PartialEq))]
#[non_exhaustive] #[non_exhaustive]
pub enum ContentTypeError { pub enum ContentTypeError {
/// Can not parse content type /// Can not parse content type
@ -398,28 +399,14 @@ pub enum ContentTypeError {
UnknownEncoding, UnknownEncoding,
} }
#[cfg(test)]
mod content_type_test_impls {
use super::*;
impl std::cmp::PartialEq for ContentTypeError {
fn eq(&self, other: &Self) -> bool {
match self {
Self::ParseError => matches!(other, ContentTypeError::ParseError),
Self::UnknownEncoding => {
matches!(other, ContentTypeError::UnknownEncoding)
}
}
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use http::{Error as HttpError, StatusCode};
use std::io; use std::io;
use http::{Error as HttpError, StatusCode};
use super::*;
#[test] #[test]
fn test_into_response() { fn test_into_response() {
let resp: Response<BoxBody> = ParseError::Incomplete.into(); let resp: Response<BoxBody> = ParseError::Incomplete.into();

View File

@ -25,10 +25,10 @@ pub trait HttpMessage: Sized {
/// Message payload stream /// Message payload stream
fn take_payload(&mut self) -> Payload<Self::Stream>; fn take_payload(&mut self) -> Payload<Self::Stream>;
/// Request's extensions container /// Returns a reference to the request-local data container.
fn extensions(&self) -> Ref<'_, Extensions>; fn extensions(&self) -> Ref<'_, Extensions>;
/// Mutable reference to a the request's extensions container /// Returns a mutable reference to the request-local data container.
fn extensions_mut(&self) -> RefMut<'_, Extensions>; fn extensions_mut(&self) -> RefMut<'_, Extensions>;
/// Get a header. /// Get a header.

View File

@ -19,7 +19,7 @@ pub struct Request<P = BoxedPayloadStream> {
pub(crate) payload: Payload<P>, pub(crate) payload: Payload<P>,
pub(crate) head: Message<RequestHead>, pub(crate) head: Message<RequestHead>,
pub(crate) conn_data: Option<Rc<Extensions>>, pub(crate) conn_data: Option<Rc<Extensions>>,
pub(crate) req_data: RefCell<Extensions>, pub(crate) extensions: RefCell<Extensions>,
} }
impl<P> HttpMessage for Request<P> { impl<P> HttpMessage for Request<P> {
@ -34,16 +34,14 @@ impl<P> HttpMessage for Request<P> {
mem::replace(&mut self.payload, Payload::None) mem::replace(&mut self.payload, Payload::None)
} }
/// Request extensions
#[inline] #[inline]
fn extensions(&self) -> Ref<'_, Extensions> { fn extensions(&self) -> Ref<'_, Extensions> {
self.req_data.borrow() self.extensions.borrow()
} }
/// Mutable reference to a the request's extensions
#[inline] #[inline]
fn extensions_mut(&self) -> RefMut<'_, Extensions> { fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.req_data.borrow_mut() self.extensions.borrow_mut()
} }
} }
@ -52,7 +50,7 @@ impl From<Message<RequestHead>> for Request<BoxedPayloadStream> {
Request { Request {
head, head,
payload: Payload::None, payload: Payload::None,
req_data: RefCell::new(Extensions::default()), extensions: RefCell::new(Extensions::default()),
conn_data: None, conn_data: None,
} }
} }
@ -65,7 +63,7 @@ impl Request<BoxedPayloadStream> {
Request { Request {
head: Message::new(), head: Message::new(),
payload: Payload::None, payload: Payload::None,
req_data: RefCell::new(Extensions::default()), extensions: RefCell::new(Extensions::default()),
conn_data: None, conn_data: None,
} }
} }
@ -77,7 +75,7 @@ impl<P> Request<P> {
Request { Request {
payload, payload,
head: Message::new(), head: Message::new(),
req_data: RefCell::new(Extensions::default()), extensions: RefCell::new(Extensions::default()),
conn_data: None, conn_data: None,
} }
} }
@ -90,7 +88,7 @@ impl<P> Request<P> {
Request { Request {
payload, payload,
head: self.head, head: self.head,
req_data: self.req_data, extensions: self.extensions,
conn_data: self.conn_data, conn_data: self.conn_data,
}, },
pl, pl,
@ -195,16 +193,17 @@ impl<P> Request<P> {
.and_then(|container| container.get::<T>()) .and_then(|container| container.get::<T>())
} }
/// Returns the connection data container if an [on-connect] callback was registered. /// Returns the connection-level data/extensions container if an [on-connect] callback was
/// registered, leaving an empty one in its place.
/// ///
/// [on-connect]: crate::HttpServiceBuilder::on_connect_ext /// [on-connect]: crate::HttpServiceBuilder::on_connect_ext
pub fn take_conn_data(&mut self) -> Option<Rc<Extensions>> { pub fn take_conn_data(&mut self) -> Option<Rc<Extensions>> {
self.conn_data.take() self.conn_data.take()
} }
/// Returns the request data container, leaving an empty one in it's place. /// Returns the request-local data/extensions container, leaving an empty one in its place.
pub fn take_req_data(&mut self) -> Extensions { pub fn take_req_data(&mut self) -> Extensions {
mem::take(self.req_data.get_mut()) mem::take(self.extensions.get_mut())
} }
} }

View File

@ -128,18 +128,6 @@ impl<B> Response<B> {
self.head.keep_alive() self.head.keep_alive()
} }
/// Returns a reference to the extensions of this response.
#[inline]
pub fn extensions(&self) -> Ref<'_, Extensions> {
self.extensions.borrow()
}
/// Returns a mutable reference to the extensions of this response.
#[inline]
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.extensions.borrow_mut()
}
/// Returns a reference to the body of this response. /// Returns a reference to the body of this response.
#[inline] #[inline]
pub fn body(&self) -> &B { pub fn body(&self) -> &B {
@ -185,7 +173,9 @@ impl<B> Response<B> {
self.replace_body(()) 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] #[inline]
pub fn map_body<F, B2>(mut self, f: F) -> Response<B2> pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
where where

View File

@ -67,7 +67,9 @@ impl<S> ClientResponse<S> {
&self.head().headers &self.head().headers
} }
/// Set a body and return previous body value /// Map the current body type to another using a closure. Returns a new response.
///
/// Closure receives the response head and the current body type.
pub fn map_body<F, U>(mut self, f: F) -> ClientResponse<U> pub fn map_body<F, U>(mut self, f: F) -> ClientResponse<U>
where where
F: FnOnce(&mut ResponseHead, Payload<S>) -> Payload<U>, F: FnOnce(&mut ResponseHead, Payload<S>) -> Payload<U>,
@ -117,18 +119,6 @@ impl<S> ClientResponse<S> {
self self
} }
/// Returns a reference to the extensions of this response.
#[inline]
pub fn req_data(&self) -> Ref<'_, Extensions> {
self.extensions.borrow()
}
/// Returns a mutable reference to the extensions of this response.
#[inline]
pub fn req_data_mut(&self) -> RefMut<'_, Extensions> {
self.extensions.borrow_mut()
}
/// Load request cookies. /// Load request cookies.
#[cfg(feature = "cookies")] #[cfg(feature = "cookies")]
pub fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> { pub fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
@ -241,11 +231,11 @@ impl<S> HttpMessage for ClientResponse<S> {
} }
fn extensions(&self) -> Ref<'_, Extensions> { fn extensions(&self) -> Ref<'_, Extensions> {
self.req_data() self.extensions.borrow()
} }
fn extensions_mut(&self) -> RefMut<'_, Extensions> { fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.req_data_mut() self.extensions.borrow_mut()
} }
} }

View File

@ -18,7 +18,7 @@ use crate::{
AppServiceFactory, BoxedHttpService, BoxedHttpServiceFactory, ServiceRequest, AppServiceFactory, BoxedHttpService, BoxedHttpServiceFactory, ServiceRequest,
ServiceResponse, ServiceResponse,
}, },
Error, HttpResponse, Error, HttpMessage, HttpResponse,
}; };
type Guards = Vec<Box<dyn Guard>>; type Guards = Vec<Box<dyn Guard>>;
@ -201,27 +201,29 @@ where
actix_service::forward_ready!(service); actix_service::forward_ready!(service);
fn call(&self, mut req: Request) -> Self::Future { fn call(&self, mut req: Request) -> Self::Future {
let req_data = Rc::new(RefCell::new(req.take_req_data())); let extensions = Rc::new(RefCell::new(req.take_req_data()));
let conn_data = req.take_conn_data(); let conn_data = req.take_conn_data();
let (head, payload) = req.into_parts(); let (head, payload) = req.into_parts();
let req = if let Some(mut req) = self.app_state.pool().pop() { let req = match self.app_state.pool().pop() {
let inner = Rc::get_mut(&mut req.inner).unwrap(); Some(mut req) => {
inner.path.get_mut().update(&head.uri); let inner = Rc::get_mut(&mut req.inner).unwrap();
inner.path.reset(); inner.path.get_mut().update(&head.uri);
inner.head = head; inner.path.reset();
inner.conn_data = conn_data; inner.head = head;
inner.req_data = req_data; inner.conn_data = conn_data;
req inner.extensions = extensions;
} else { req
HttpRequest::new( }
None => HttpRequest::new(
Path::new(Url::new(head.uri.clone())), Path::new(Url::new(head.uri.clone())),
head, head,
self.app_state.clone(), Rc::clone(&self.app_state),
self.app_data.clone(), Rc::clone(&self.app_data),
conn_data, conn_data,
req_data, extensions,
) ),
}; };
self.service.call(ServiceRequest::new(req, payload)) self.service.call(ServiceRequest::new(req, payload))

View File

@ -41,7 +41,7 @@ pub(crate) struct HttpRequestInner {
pub(crate) path: Path<Url>, pub(crate) path: Path<Url>,
pub(crate) app_data: SmallVec<[Rc<Extensions>; 4]>, pub(crate) app_data: SmallVec<[Rc<Extensions>; 4]>,
pub(crate) conn_data: Option<Rc<Extensions>>, pub(crate) conn_data: Option<Rc<Extensions>>,
pub(crate) req_data: Rc<RefCell<Extensions>>, pub(crate) extensions: Rc<RefCell<Extensions>>,
app_state: Rc<AppInitServiceState>, app_state: Rc<AppInitServiceState>,
} }
@ -53,7 +53,7 @@ impl HttpRequest {
app_state: Rc<AppInitServiceState>, app_state: Rc<AppInitServiceState>,
app_data: Rc<Extensions>, app_data: Rc<Extensions>,
conn_data: Option<Rc<Extensions>>, conn_data: Option<Rc<Extensions>>,
req_data: Rc<RefCell<Extensions>>, extensions: Rc<RefCell<Extensions>>,
) -> HttpRequest { ) -> HttpRequest {
let mut data = SmallVec::<[Rc<Extensions>; 4]>::new(); let mut data = SmallVec::<[Rc<Extensions>; 4]>::new();
data.push(app_data); data.push(app_data);
@ -65,7 +65,7 @@ impl HttpRequest {
app_state, app_state,
app_data: data, app_data: data,
conn_data, conn_data,
req_data, extensions,
}), }),
} }
} }
@ -162,14 +162,6 @@ impl HttpRequest {
self.resource_map().match_name(self.path()) self.resource_map().match_name(self.path())
} }
pub fn req_data(&self) -> Ref<'_, Extensions> {
self.inner.req_data.borrow()
}
pub fn req_data_mut(&self) -> RefMut<'_, Extensions> {
self.inner.req_data.borrow_mut()
}
/// Returns a reference a piece of connection data set in an [on-connect] callback. /// Returns a reference a piece of connection data set in an [on-connect] callback.
/// ///
/// ```ignore /// ```ignore
@ -359,12 +351,12 @@ impl HttpMessage for HttpRequest {
#[inline] #[inline]
fn extensions(&self) -> Ref<'_, Extensions> { fn extensions(&self) -> Ref<'_, Extensions> {
self.req_data() self.inner.extensions.borrow()
} }
#[inline] #[inline]
fn extensions_mut(&self) -> RefMut<'_, Extensions> { fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.req_data_mut() self.inner.extensions.borrow_mut()
} }
#[inline] #[inline]
@ -385,7 +377,10 @@ impl Drop for HttpRequest {
// Inner is borrowed mut here and; get req data mutably to reduce borrow check. Also // Inner is borrowed mut here and; get req data mutably to reduce borrow check. Also
// we know the req_data Rc will not have any cloned at this point to unwrap is okay. // we know the req_data Rc will not have any cloned at this point to unwrap is okay.
Rc::get_mut(&mut inner.req_data).unwrap().get_mut().clear(); Rc::get_mut(&mut inner.extensions)
.unwrap()
.get_mut()
.clear();
// a re-borrow of pool is necessary here. // a re-borrow of pool is necessary here.
let req = Rc::clone(&self.inner); let req = Rc::clone(&self.inner);

View File

@ -22,7 +22,7 @@ use {
cookie::Cookie, cookie::Cookie,
}; };
use crate::{error::Error, HttpRequest, HttpResponseBuilder, Responder}; use crate::{error::Error, HttpMessage, HttpRequest, HttpResponseBuilder, Responder};
/// An outgoing response. /// An outgoing response.
pub struct HttpResponse<B = BoxBody> { pub struct HttpResponse<B = BoxBody> {
@ -216,7 +216,9 @@ impl<B> HttpResponse<B> {
} }
} }
/// Set a body and return previous body value /// Map the current body type to another using a closure. Returns a new response.
///
/// Closure receives the response head and the current body type.
pub fn map_body<F, B2>(self, f: F) -> HttpResponse<B2> pub fn map_body<F, B2>(self, f: F) -> HttpResponse<B2>
where where
F: FnOnce(&mut ResponseHead, B) -> B2, F: FnOnce(&mut ResponseHead, B) -> B2,

View File

@ -399,32 +399,32 @@ impl<B> ServiceResponse<B> {
ServiceResponse::new(self.request, response) ServiceResponse::new(self.request, response)
} }
/// Get reference to original request /// Returns reference to original request.
#[inline] #[inline]
pub fn request(&self) -> &HttpRequest { pub fn request(&self) -> &HttpRequest {
&self.request &self.request
} }
/// Get reference to response /// Returns reference to response.
#[inline] #[inline]
pub fn response(&self) -> &HttpResponse<B> { pub fn response(&self) -> &HttpResponse<B> {
&self.response &self.response
} }
/// Get mutable reference to response /// Returns mutable reference to response.
#[inline] #[inline]
pub fn response_mut(&mut self) -> &mut HttpResponse<B> { pub fn response_mut(&mut self) -> &mut HttpResponse<B> {
&mut self.response &mut self.response
} }
/// Get the response status code /// Returns response status code.
#[inline] #[inline]
pub fn status(&self) -> StatusCode { pub fn status(&self) -> StatusCode {
self.response.status() self.response.status()
} }
#[inline]
/// Returns response's headers. /// Returns response's headers.
#[inline]
pub fn headers(&self) -> &HeaderMap { pub fn headers(&self) -> &HeaderMap {
self.response.headers() self.response.headers()
} }
@ -441,13 +441,9 @@ impl<B> ServiceResponse<B> {
(self.request, self.response) (self.request, self.response)
} }
/// Extract response body /// Map the current body type to another using a closure. Returns a new response.
#[inline] ///
pub fn into_body(self) -> B { /// Closure receives the response head and the current body type.
self.response.into_body()
}
/// Set a new body
#[inline] #[inline]
pub fn map_body<F, B2>(self, f: F) -> ServiceResponse<B2> pub fn map_body<F, B2>(self, f: F) -> ServiceResponse<B2>
where where
@ -478,6 +474,12 @@ impl<B> ServiceResponse<B> {
{ {
self.map_body(|_, body| body.boxed()) self.map_body(|_, body| body.boxed())
} }
/// Consumes the response and returns its body.
#[inline]
pub fn into_body(self) -> B {
self.response.into_body()
}
} }
impl<B> From<ServiceResponse<B>> for HttpResponse<B> { impl<B> From<ServiceResponse<B>> for HttpResponse<B> {