mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-01 00:44:26 +02:00
add connection level data container (#2491)
This commit is contained in:
@ -197,7 +197,8 @@ where
|
||||
|
||||
actix_service::forward_ready!(service);
|
||||
|
||||
fn call(&self, req: Request) -> Self::Future {
|
||||
fn call(&self, mut req: Request) -> Self::Future {
|
||||
let conn_data = req.take_conn_data();
|
||||
let (head, payload) = req.into_parts();
|
||||
|
||||
let req = if let Some(mut req) = self.app_state.pool().pop() {
|
||||
@ -205,6 +206,7 @@ where
|
||||
inner.path.get_mut().update(&head.uri);
|
||||
inner.path.reset();
|
||||
inner.head = head;
|
||||
inner.conn_data = conn_data;
|
||||
req
|
||||
} else {
|
||||
HttpRequest::new(
|
||||
@ -212,6 +214,7 @@ where
|
||||
head,
|
||||
self.app_state.clone(),
|
||||
self.app_data.clone(),
|
||||
conn_data,
|
||||
)
|
||||
};
|
||||
self.service.call(ServiceRequest::new(req, payload))
|
||||
|
@ -37,6 +37,7 @@ pub(crate) struct HttpRequestInner {
|
||||
pub(crate) head: Message<RequestHead>,
|
||||
pub(crate) path: Path<Url>,
|
||||
pub(crate) app_data: SmallVec<[Rc<Extensions>; 4]>,
|
||||
pub(crate) conn_data: Option<Rc<Extensions>>,
|
||||
app_state: Rc<AppInitServiceState>,
|
||||
}
|
||||
|
||||
@ -47,6 +48,7 @@ impl HttpRequest {
|
||||
head: Message<RequestHead>,
|
||||
app_state: Rc<AppInitServiceState>,
|
||||
app_data: Rc<Extensions>,
|
||||
conn_data: Option<Rc<Extensions>>,
|
||||
) -> HttpRequest {
|
||||
let mut data = SmallVec::<[Rc<Extensions>; 4]>::new();
|
||||
data.push(app_data);
|
||||
@ -57,6 +59,7 @@ impl HttpRequest {
|
||||
path,
|
||||
app_state,
|
||||
app_data: data,
|
||||
conn_data,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -165,6 +168,20 @@ impl HttpRequest {
|
||||
self.head().extensions_mut()
|
||||
}
|
||||
|
||||
/// Returns a reference a piece of connection data set in an [on-connect] callback.
|
||||
///
|
||||
/// ```ignore
|
||||
/// let opt_t = req.conn_data::<PeerCertificate>();
|
||||
/// ```
|
||||
///
|
||||
/// [on-connect]: crate::HttpServiceBuilder::on_connect_ext
|
||||
pub fn conn_data<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner
|
||||
.conn_data
|
||||
.as_deref()
|
||||
.and_then(|container| container.get::<T>())
|
||||
}
|
||||
|
||||
/// Generates URL for a named resource.
|
||||
///
|
||||
/// This substitutes in sequence all URL parameters that appear in the resource itself and in
|
||||
|
@ -101,9 +101,9 @@ where
|
||||
|
||||
/// Sets function that will be called once before each connection is handled.
|
||||
/// It will receive a `&std::any::Any`, which contains underlying connection type and an
|
||||
/// [Extensions] container so that request-local data can be passed to middleware and handlers.
|
||||
/// [Extensions] container so that connection data can be accessed in middleware and handlers.
|
||||
///
|
||||
/// For example:
|
||||
/// # Connection Types
|
||||
/// - `actix_tls::accept::openssl::TlsStream<actix_web::rt::net::TcpStream>` when using openssl.
|
||||
/// - `actix_tls::accept::rustls::TlsStream<actix_web::rt::net::TcpStream>` when using rustls.
|
||||
/// - `actix_web::rt::net::TcpStream` when no encryption is used.
|
||||
|
@ -172,12 +172,10 @@ impl ServiceRequest {
|
||||
self.head().uri.path()
|
||||
}
|
||||
|
||||
/// The query string in the URL.
|
||||
///
|
||||
/// E.g., id=10
|
||||
/// Counterpart to [`HttpRequest::query_string`](super::HttpRequest::query_string()).
|
||||
#[inline]
|
||||
pub fn query_string(&self) -> &str {
|
||||
self.uri().query().unwrap_or_default()
|
||||
self.req.query_string()
|
||||
}
|
||||
|
||||
/// Peer socket address.
|
||||
@ -241,6 +239,7 @@ impl ServiceRequest {
|
||||
}
|
||||
|
||||
/// Counterpart to [`HttpRequest::app_data`](super::HttpRequest::app_data()).
|
||||
#[inline]
|
||||
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
||||
for container in self.req.inner.app_data.iter().rev() {
|
||||
if let Some(data) = container.get::<T>() {
|
||||
@ -251,6 +250,12 @@ impl ServiceRequest {
|
||||
None
|
||||
}
|
||||
|
||||
/// Counterpart to [`HttpRequest::conn_data`](super::HttpRequest::conn_data()).
|
||||
#[inline]
|
||||
pub fn conn_data<T: 'static>(&self) -> Option<&T> {
|
||||
self.req.conn_data()
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
||||
self.req.cookies()
|
||||
@ -263,6 +268,7 @@ impl ServiceRequest {
|
||||
}
|
||||
|
||||
/// Set request payload.
|
||||
#[inline]
|
||||
pub fn set_payload(&mut self, payload: Payload) {
|
||||
self.payload = payload;
|
||||
}
|
||||
@ -280,6 +286,7 @@ impl ServiceRequest {
|
||||
}
|
||||
|
||||
impl Resource<Url> for ServiceRequest {
|
||||
#[inline]
|
||||
fn resource_path(&mut self) -> &mut Path<Url> {
|
||||
self.match_info_mut()
|
||||
}
|
||||
@ -404,12 +411,11 @@ impl<B> ServiceResponse<B> {
|
||||
}
|
||||
|
||||
/// Extract response body
|
||||
#[inline]
|
||||
pub fn into_body(self) -> B {
|
||||
self.response.into_body()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> ServiceResponse<B> {
|
||||
/// Set a new body
|
||||
#[inline]
|
||||
pub fn map_body<F, B2>(self, f: F) -> ServiceResponse<B2>
|
||||
|
@ -581,7 +581,7 @@ impl TestRequest {
|
||||
let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
|
||||
|
||||
ServiceRequest::new(
|
||||
HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data)),
|
||||
HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data), None),
|
||||
payload,
|
||||
)
|
||||
}
|
||||
@ -599,7 +599,7 @@ impl TestRequest {
|
||||
|
||||
let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
|
||||
|
||||
HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data))
|
||||
HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data), None)
|
||||
}
|
||||
|
||||
/// Complete request creation and generate `HttpRequest` and `Payload` instances
|
||||
@ -610,7 +610,7 @@ impl TestRequest {
|
||||
|
||||
let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
|
||||
|
||||
let req = HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data));
|
||||
let req = HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data), None);
|
||||
|
||||
(req, payload)
|
||||
}
|
||||
|
Reference in New Issue
Block a user