mirror of https://github.com/fafhrd91/actix-web
move payload type out of HttpRequest
This commit is contained in:
parent
d40ae8c8ca
commit
7db0ded43b
|
@ -4,8 +4,11 @@
|
||||||
### Changed
|
### Changed
|
||||||
* Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly.
|
* Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly.
|
||||||
Making it more simple and performant. [#1891]
|
Making it more simple and performant. [#1891]
|
||||||
|
* `ServiceRequest::into_parts` and `ServiceRequest::from_parts` would not fail.
|
||||||
|
`ServiceRequest::from_request` would not fail and no payload would be generated [#1893]
|
||||||
|
|
||||||
[#1891]: https://github.com/actix/actix-web/pull/1891
|
[#1891]: https://github.com/actix/actix-web/pull/1891
|
||||||
|
[#1893]: https://github.com/actix/actix-web/pull/1893
|
||||||
|
|
||||||
## 4.0.0-beta.1 - 2021-01-07
|
## 4.0.0-beta.1 - 2021-01-07
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::Poll;
|
||||||
|
|
||||||
use actix_http::{Extensions, Request, Response};
|
use actix_http::{Extensions, Request, Response};
|
||||||
use actix_router::{Path, ResourceDef, Router, Url};
|
use actix_router::{Path, ResourceDef, Router, Url};
|
||||||
|
@ -170,9 +170,7 @@ where
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
type Future = T::Future;
|
type Future = T::Future;
|
||||||
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
actix_service::forward_ready!(service);
|
||||||
self.service.poll_ready(cx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
let (head, payload) = req.into_parts();
|
let (head, payload) = req.into_parts();
|
||||||
|
@ -182,20 +180,18 @@ where
|
||||||
inner.path.get_mut().update(&head.uri);
|
inner.path.get_mut().update(&head.uri);
|
||||||
inner.path.reset();
|
inner.path.reset();
|
||||||
inner.head = head;
|
inner.head = head;
|
||||||
inner.payload = payload;
|
|
||||||
req
|
req
|
||||||
} else {
|
} else {
|
||||||
HttpRequest::new(
|
HttpRequest::new(
|
||||||
Path::new(Url::new(head.uri.clone())),
|
Path::new(Url::new(head.uri.clone())),
|
||||||
head,
|
head,
|
||||||
payload,
|
|
||||||
self.rmap.clone(),
|
self.rmap.clone(),
|
||||||
self.config.clone(),
|
self.config.clone(),
|
||||||
self.app_data.clone(),
|
self.app_data.clone(),
|
||||||
self.pool,
|
self.pool,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.service.call(ServiceRequest::new(req))
|
self.service.call(ServiceRequest::new(req, payload))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ pub struct HttpRequest {
|
||||||
pub(crate) struct HttpRequestInner {
|
pub(crate) struct HttpRequestInner {
|
||||||
pub(crate) head: Message<RequestHead>,
|
pub(crate) head: Message<RequestHead>,
|
||||||
pub(crate) path: Path<Url>,
|
pub(crate) path: Path<Url>,
|
||||||
pub(crate) payload: Payload,
|
|
||||||
pub(crate) app_data: SmallVec<[Rc<Extensions>; 4]>,
|
pub(crate) app_data: SmallVec<[Rc<Extensions>; 4]>,
|
||||||
rmap: Rc<ResourceMap>,
|
rmap: Rc<ResourceMap>,
|
||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
|
@ -38,7 +37,6 @@ impl HttpRequest {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
path: Path<Url>,
|
path: Path<Url>,
|
||||||
head: Message<RequestHead>,
|
head: Message<RequestHead>,
|
||||||
payload: Payload,
|
|
||||||
rmap: Rc<ResourceMap>,
|
rmap: Rc<ResourceMap>,
|
||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
app_data: Rc<Extensions>,
|
app_data: Rc<Extensions>,
|
||||||
|
@ -51,7 +49,6 @@ impl HttpRequest {
|
||||||
inner: Rc::new(HttpRequestInner {
|
inner: Rc::new(HttpRequestInner {
|
||||||
head,
|
head,
|
||||||
path,
|
path,
|
||||||
payload,
|
|
||||||
rmap,
|
rmap,
|
||||||
config,
|
config,
|
||||||
app_data: data,
|
app_data: data,
|
||||||
|
|
104
src/service.rs
104
src/service.rs
|
@ -52,75 +52,63 @@ where
|
||||||
/// An service http request
|
/// An service http request
|
||||||
///
|
///
|
||||||
/// ServiceRequest allows mutable access to request's internal structures
|
/// ServiceRequest allows mutable access to request's internal structures
|
||||||
pub struct ServiceRequest(HttpRequest);
|
pub struct ServiceRequest {
|
||||||
|
req: HttpRequest,
|
||||||
|
payload: Payload,
|
||||||
|
}
|
||||||
|
|
||||||
impl ServiceRequest {
|
impl ServiceRequest {
|
||||||
/// Construct service request
|
/// Construct service request
|
||||||
pub(crate) fn new(req: HttpRequest) -> Self {
|
pub(crate) fn new(req: HttpRequest, payload: Payload) -> Self {
|
||||||
ServiceRequest(req)
|
Self { req, payload }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deconstruct request into parts
|
/// Deconstruct request into parts
|
||||||
pub fn into_parts(mut self) -> (HttpRequest, Payload) {
|
#[inline]
|
||||||
let pl = Rc::get_mut(&mut (self.0).inner).unwrap().payload.take();
|
pub fn into_parts(self) -> (HttpRequest, Payload) {
|
||||||
(self.0, pl)
|
(self.req, self.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct request from parts.
|
/// Construct request from parts.
|
||||||
///
|
///
|
||||||
/// `ServiceRequest` can be re-constructed only if `req` hasn't been cloned.
|
/// `ServiceRequest` can be re-constructed only if `req` hasn't been cloned.
|
||||||
pub fn from_parts(
|
pub fn from_parts(req: HttpRequest, payload: Payload) -> Self {
|
||||||
mut req: HttpRequest,
|
Self { req, payload }
|
||||||
pl: Payload,
|
|
||||||
) -> Result<Self, (HttpRequest, Payload)> {
|
|
||||||
match Rc::get_mut(&mut req.inner) {
|
|
||||||
Some(p) => {
|
|
||||||
p.payload = pl;
|
|
||||||
Ok(ServiceRequest(req))
|
|
||||||
}
|
|
||||||
None => Err((req, pl)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct request from request.
|
/// Construct request from request.
|
||||||
///
|
///
|
||||||
/// `HttpRequest` implements `Clone` trait via `Rc` type. `ServiceRequest`
|
/// The returned `ServiceRequest` would have no payload.
|
||||||
/// can be re-constructed only if rc's strong pointers count eq 1 and
|
pub fn from_request(req: HttpRequest) -> Self {
|
||||||
/// weak pointers count is 0.
|
ServiceRequest {
|
||||||
pub fn from_request(req: HttpRequest) -> Result<Self, HttpRequest> {
|
req,
|
||||||
// There is no weak pointer used on HttpRequest so intentionally
|
payload: Payload::None,
|
||||||
// ignore the check.
|
|
||||||
if Rc::strong_count(&req.inner) == 1 {
|
|
||||||
debug_assert!(Rc::weak_count(&req.inner) == 0);
|
|
||||||
Ok(ServiceRequest(req))
|
|
||||||
} else {
|
|
||||||
Err(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create service response
|
/// Create service response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_response<B, R: Into<Response<B>>>(self, res: R) -> ServiceResponse<B> {
|
pub fn into_response<B, R: Into<Response<B>>>(self, res: R) -> ServiceResponse<B> {
|
||||||
ServiceResponse::new(self.0, res.into())
|
ServiceResponse::new(self.req, res.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create service response for error
|
/// Create service response for error
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn error_response<B, E: Into<Error>>(self, err: E) -> ServiceResponse<B> {
|
pub fn error_response<B, E: Into<Error>>(self, err: E) -> ServiceResponse<B> {
|
||||||
let res: Response = err.into().into();
|
let res: Response = err.into().into();
|
||||||
ServiceResponse::new(self.0, res.into_body())
|
ServiceResponse::new(self.req, res.into_body())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method returns reference to the request head
|
/// This method returns reference to the request head
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn head(&self) -> &RequestHead {
|
pub fn head(&self) -> &RequestHead {
|
||||||
&self.0.head()
|
&self.req.head()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method returns reference to the request head
|
/// This method returns reference to the request head
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn head_mut(&mut self) -> &mut RequestHead {
|
pub fn head_mut(&mut self) -> &mut RequestHead {
|
||||||
self.0.head_mut()
|
self.req.head_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request's uri.
|
/// Request's uri.
|
||||||
|
@ -196,42 +184,42 @@ impl ServiceRequest {
|
||||||
/// access the matched value for that segment.
|
/// access the matched value for that segment.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn match_info(&self) -> &Path<Url> {
|
pub fn match_info(&self) -> &Path<Url> {
|
||||||
self.0.match_info()
|
self.req.match_info()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Counterpart to [`HttpRequest::match_name`](super::HttpRequest::match_name()).
|
/// Counterpart to [`HttpRequest::match_name`](super::HttpRequest::match_name()).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn match_name(&self) -> Option<&str> {
|
pub fn match_name(&self) -> Option<&str> {
|
||||||
self.0.match_name()
|
self.req.match_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Counterpart to [`HttpRequest::match_pattern`](super::HttpRequest::match_pattern()).
|
/// Counterpart to [`HttpRequest::match_pattern`](super::HttpRequest::match_pattern()).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn match_pattern(&self) -> Option<String> {
|
pub fn match_pattern(&self) -> Option<String> {
|
||||||
self.0.match_pattern()
|
self.req.match_pattern()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get a mutable reference to the Path parameters.
|
/// Get a mutable reference to the Path parameters.
|
||||||
pub fn match_info_mut(&mut self) -> &mut Path<Url> {
|
pub fn match_info_mut(&mut self) -> &mut Path<Url> {
|
||||||
self.0.match_info_mut()
|
self.req.match_info_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get a reference to a `ResourceMap` of current application.
|
/// Get a reference to a `ResourceMap` of current application.
|
||||||
pub fn resource_map(&self) -> &ResourceMap {
|
pub fn resource_map(&self) -> &ResourceMap {
|
||||||
self.0.resource_map()
|
self.req.resource_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Service configuration
|
/// Service configuration
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn app_config(&self) -> &AppConfig {
|
pub fn app_config(&self) -> &AppConfig {
|
||||||
self.0.app_config()
|
self.req.app_config()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Counterpart to [`HttpRequest::app_data`](super::HttpRequest::app_data()).
|
/// Counterpart to [`HttpRequest::app_data`](super::HttpRequest::app_data()).
|
||||||
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
||||||
for container in (self.0).inner.app_data.iter().rev() {
|
for container in self.req.inner.app_data.iter().rev() {
|
||||||
if let Some(data) = container.get::<T>() {
|
if let Some(data) = container.get::<T>() {
|
||||||
return Some(data);
|
return Some(data);
|
||||||
}
|
}
|
||||||
|
@ -242,13 +230,13 @@ impl ServiceRequest {
|
||||||
|
|
||||||
/// Set request payload.
|
/// Set request payload.
|
||||||
pub fn set_payload(&mut self, payload: Payload) {
|
pub fn set_payload(&mut self, payload: Payload) {
|
||||||
Rc::get_mut(&mut (self.0).inner).unwrap().payload = payload;
|
self.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Add app data container to request's resolution set.
|
/// Add app data container to request's resolution set.
|
||||||
pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
|
pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
|
||||||
Rc::get_mut(&mut (self.0).inner)
|
Rc::get_mut(&mut (self.req).inner)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.app_data
|
.app_data
|
||||||
.push(extensions);
|
.push(extensions);
|
||||||
|
@ -273,18 +261,18 @@ impl HttpMessage for ServiceRequest {
|
||||||
/// Request extensions
|
/// Request extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extensions(&self) -> Ref<'_, Extensions> {
|
fn extensions(&self) -> Ref<'_, Extensions> {
|
||||||
self.0.extensions()
|
self.req.extensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable reference to a the request's extensions
|
/// Mutable reference to a the request's extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
||||||
self.0.extensions_mut()
|
self.req.extensions_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn take_payload(&mut self) -> Payload<Self::Stream> {
|
fn take_payload(&mut self) -> Payload<Self::Stream> {
|
||||||
Rc::get_mut(&mut (self.0).inner).unwrap().payload.take()
|
self.payload.take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,23 +542,23 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_service_request() {
|
fn test_service_request() {
|
||||||
let req = TestRequest::default().to_srv_request();
|
// let req = TestRequest::default().to_srv_request();
|
||||||
let (r, pl) = req.into_parts();
|
// let (r, pl) = req.into_parts();
|
||||||
assert!(ServiceRequest::from_parts(r, pl).is_ok());
|
// assert!(ServiceRequest::from_parts(r, pl).is_ok());
|
||||||
|
|
||||||
let req = TestRequest::default().to_srv_request();
|
// let req = TestRequest::default().to_srv_request();
|
||||||
let (r, pl) = req.into_parts();
|
// let (r, pl) = req.into_parts();
|
||||||
let _r2 = r.clone();
|
// let _r2 = r.clone();
|
||||||
assert!(ServiceRequest::from_parts(r, pl).is_err());
|
// assert!(ServiceRequest::from_parts(r, pl).is_err());
|
||||||
|
|
||||||
let req = TestRequest::default().to_srv_request();
|
// let req = TestRequest::default().to_srv_request();
|
||||||
let (r, _pl) = req.into_parts();
|
// let (r, _pl) = req.into_parts();
|
||||||
assert!(ServiceRequest::from_request(r).is_ok());
|
// assert!(ServiceRequest::from_request(r).is_ok());
|
||||||
|
|
||||||
let req = TestRequest::default().to_srv_request();
|
// let req = TestRequest::default().to_srv_request();
|
||||||
let (r, _pl) = req.into_parts();
|
// let (r, _pl) = req.into_parts();
|
||||||
let _r2 = r.clone();
|
// let _r2 = r.clone();
|
||||||
assert!(ServiceRequest::from_request(r).is_err());
|
// assert!(ServiceRequest::from_request(r).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
|
12
src/test.rs
12
src/test.rs
|
@ -542,15 +542,17 @@ impl TestRequest {
|
||||||
head.peer_addr = self.peer_addr;
|
head.peer_addr = self.peer_addr;
|
||||||
self.path.get_mut().update(&head.uri);
|
self.path.get_mut().update(&head.uri);
|
||||||
|
|
||||||
ServiceRequest::new(HttpRequest::new(
|
ServiceRequest::new(
|
||||||
|
HttpRequest::new(
|
||||||
self.path,
|
self.path,
|
||||||
head,
|
head,
|
||||||
payload,
|
|
||||||
Rc::new(self.rmap),
|
Rc::new(self.rmap),
|
||||||
self.config.clone(),
|
self.config.clone(),
|
||||||
Rc::new(self.app_data),
|
Rc::new(self.app_data),
|
||||||
HttpRequestPool::create(),
|
HttpRequestPool::create(),
|
||||||
))
|
),
|
||||||
|
payload,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Complete request creation and generate `ServiceResponse` instance
|
/// Complete request creation and generate `ServiceResponse` instance
|
||||||
|
@ -560,14 +562,13 @@ impl TestRequest {
|
||||||
|
|
||||||
/// Complete request creation and generate `HttpRequest` instance
|
/// Complete request creation and generate `HttpRequest` instance
|
||||||
pub fn to_http_request(mut self) -> HttpRequest {
|
pub fn to_http_request(mut self) -> HttpRequest {
|
||||||
let (mut head, payload) = self.req.finish().into_parts();
|
let (mut head, _) = self.req.finish().into_parts();
|
||||||
head.peer_addr = self.peer_addr;
|
head.peer_addr = self.peer_addr;
|
||||||
self.path.get_mut().update(&head.uri);
|
self.path.get_mut().update(&head.uri);
|
||||||
|
|
||||||
HttpRequest::new(
|
HttpRequest::new(
|
||||||
self.path,
|
self.path,
|
||||||
head,
|
head,
|
||||||
payload,
|
|
||||||
Rc::new(self.rmap),
|
Rc::new(self.rmap),
|
||||||
self.config.clone(),
|
self.config.clone(),
|
||||||
Rc::new(self.app_data),
|
Rc::new(self.app_data),
|
||||||
|
@ -584,7 +585,6 @@ impl TestRequest {
|
||||||
let req = HttpRequest::new(
|
let req = HttpRequest::new(
|
||||||
self.path,
|
self.path,
|
||||||
head,
|
head,
|
||||||
Payload::None,
|
|
||||||
Rc::new(self.rmap),
|
Rc::new(self.rmap),
|
||||||
self.config.clone(),
|
self.config.clone(),
|
||||||
Rc::new(self.app_data),
|
Rc::new(self.app_data),
|
||||||
|
|
Loading…
Reference in New Issue