1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-08-22 21:55:10 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Nikolay Kim
d7040dc303 alpha.6 release 2019-04-14 08:09:32 -07:00
Nikolay Kim
6bc1a0c76b Do not set default headers for websocket request 2019-04-14 07:43:53 -07:00
Nikolay Kim
5bd5651faa Allow to use any service as default service 2019-04-13 22:25:00 -07:00
Nikolay Kim
32ac159ba2 update migration 2019-04-13 16:51:41 -07:00
Nikolay Kim
ee33f52736 make extractor config type explicit 2019-04-13 16:35:25 -07:00
Nikolay Kim
4f30fa9d46 Remove generic type for request payload, always use default 2019-04-13 14:50:54 -07:00
Nikolay Kim
043f6e77ae remove nested multipart support 2019-04-13 10:11:07 -07:00
Nikolay Kim
48518df883 do not generate all docs; use docs.rs for 1.0 docs 2019-04-13 09:35:23 -07:00
57 changed files with 1152 additions and 1529 deletions

View File

@@ -42,7 +42,7 @@ script:
after_success:
- |
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
cargo doc --all-features &&
cargo doc --no-deps --all-features &&
echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html &&
git clone https://github.com/davisp/ghp-import.git &&
./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&

View File

@@ -1,5 +1,19 @@
# Changes
## [1.0.0-alpha.6] - 2019-04-14
### Changed
* Allow to use any service as default service.
* Remove generic type for request payload, always use default.
* Removed `Decompress` middleware. Bytes, String, Json, Form extractors
automatically decompress payload.
* Make extractor config type explicit. Add `FromRequest::Config` associated type.
## [1.0.0-alpha.5] - 2019-04-12
### Added

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-web"
version = "1.0.0-alpha.5"
version = "1.0.0-alpha.6"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
readme = "README.md"
@@ -70,18 +70,18 @@ actix-service = "0.3.6"
actix-utils = "0.3.4"
actix-router = "0.1.2"
actix-rt = "0.2.2"
actix-web-codegen = "0.1.0-alpha.1"
actix-web-codegen = "0.1.0-alpha.6"
actix-http = { version = "0.1.0-alpha.5", features=["fail"] }
actix-server = "0.4.2"
actix-server-config = "0.1.0"
actix-threadpool = "0.1.0"
awc = { version = "0.1.0-alpha.5", optional = true }
awc = { version = "0.1.0-alpha.6", optional = true }
bytes = "0.4"
derive_more = "0.14"
encoding = "0.2"
futures = "0.1"
hashbrown = "0.1.8"
hashbrown = "0.2.1"
log = "0.4"
mime = "0.3"
net2 = "0.2.33"
@@ -100,6 +100,7 @@ rustls = { version = "^0.15", optional = true }
[dev-dependencies]
actix-http = { version = "0.1.0-alpha.5", features=["ssl", "brotli", "flate2-zlib"] }
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
actix-files = { version = "0.1.0-alpha.6" }
rand = "0.6"
env_logger = "0.6"
serde_derive = "1.0"

View File

@@ -1,7 +1,7 @@
## 1.0
* Resource registration. 1.0 version uses generalized resource
registration via `.service()` method.
registration via `.service()` method.
instead of
@@ -44,9 +44,41 @@ registration via `.service()` method.
);
```
* `.with()`, `.with_async()` registration methods have been renamed to `.to()` and `.to_async()`.
instead of
```rust
App.new().resource("/welcome", |r| r.with(welcome))
```
use `.to()` or `.to_async()` methods
```rust
App.new().service(web::resource("/welcome").to(welcome))
```
* Passing arguments to handler with extractors, multiple arguments are allowed
instead of
```rust
fn welcome((body, req): (Bytes, HttpRequest)) -> ... {
...
}
```
use multiple arguments
```rust
fn welcome(body: Bytes, req: HttpRequest) -> ... {
...
}
```
* `.f()`, `.a()` and `.h()` handler registration methods have been removed.
Use `.to()` for handlers and `.to_async()` for async handlers. Handler function
must use extractors.
Use `.to()` for handlers and `.to_async()` for async handlers. Handler function
must use extractors.
instead of
@@ -61,8 +93,8 @@ must use extractors.
```
* `State` is now `Data`. You register Data during the App initialization process
and then access it from handlers either using a Data extractor or using
HttpRequest's api.
and then access it from handlers either using a Data extractor or using
HttpRequest's api.
instead of
@@ -150,6 +182,8 @@ HttpRequest's api.
}
```
* `actix_web::server` module has been removed. To start http server use `actix_web::HttpServer` type
* StaticFiles and NamedFile has been move to separate create.
instead of `use actix_web::fs::StaticFile`
@@ -166,10 +200,10 @@ HttpRequest's api.
use `use actix_multipart::Multipart`
* Request/response compression/decompression is not enabled by default.
To enable use `App::enable_encoding()` method.
* Response compression is not enabled by default.
To enable, use `Compress` middleware, `App::new().wrap(Compress::default())`.
* `actix_web::server` module has been removed. To start http server use `actix_web::HttpServer` type
* Session middleware moved to actix-session crate
* Actors support have been moved to `actix-web-actors` crate

View File

@@ -18,8 +18,8 @@ Actix web is a simple, pragmatic and extremely fast web framework for Rust.
## Documentation & community resources
* [User Guide](https://actix.rs/docs/)
* [API Documentation (Development)](https://actix.rs/actix-web/actix_web/)
* [API Documentation (0.7 Release)](https://docs.rs/actix-web/0.7.19/actix_web/)
* [API Documentation (1.0)](https://docs.rs/actix-web/)
* [API Documentation (0.7)](https://docs.rs/actix-web/0.7.19/actix_web/)
* [Chat on gitter](https://gitter.im/actix/actix)
* Cargo package: [actix-web](https://crates.io/crates/actix-web)
* Minimum supported Rust version: 1.32 or later
@@ -36,8 +36,7 @@ fn index(info: web::Path<(u32, String)>) -> impl Responder {
fn main() -> std::io::Result<()> {
HttpServer::new(
|| App::new().service(
web::resource("/{id}/{name}/index.html")
.route(web::get().to(index))))
web::resource("/{id}/{name}/index.html").to(index)))
.bind("127.0.0.1:8080")?
.run()
}

View File

@@ -1,15 +1,17 @@
# Changes
## [0.1.0-alpha.6] - 2019-04-14
* Update actix-web to alpha6
## [0.1.0-alpha.4] - 2019-04-08
* Update actix-web to alpha4
## [0.1.0-alpha.2] - 2019-04-02
* Add default handler support
## [0.1.0-alpha.1] - 2019-03-28
* Initial impl

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-files"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.6"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Static files support for actix web."
readme = "README.md"
@@ -18,7 +18,7 @@ name = "actix_files"
path = "src/lib.rs"
[dependencies]
actix-web = "1.0.0-alpha.5"
actix-web = "1.0.0-alpha.6"
actix-service = "0.3.4"
bitflags = "1"
bytes = "0.4"
@@ -31,4 +31,4 @@ percent-encoding = "1.0"
v_htmlescape = "0.4"
[dev-dependencies]
actix-web = { version = "1.0.0-alpha.5", features=["ssl"] }
actix-web = { version = "1.0.0-alpha.6", features=["ssl"] }

View File

@@ -32,9 +32,8 @@ use self::error::{FilesError, UriSegmentError};
pub use crate::named::NamedFile;
pub use crate::range::HttpRange;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
/// Return the MIME type associated with a filename extension (case-insensitive).
/// If `ext` is empty or no associated type for the extension was found, returns
@@ -225,18 +224,18 @@ type MimeOverride = Fn(&mime::Name) -> DispositionType;
/// .service(fs::Files::new("/static", "."));
/// }
/// ```
pub struct Files<S> {
pub struct Files {
path: String,
directory: PathBuf,
index: Option<String>,
show_index: bool,
default: Rc<RefCell<Option<Rc<HttpNewService<S>>>>>,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
renderer: Rc<DirectoryRenderer>,
mime_override: Option<Rc<MimeOverride>>,
file_flags: named::Flags,
}
impl<S> Clone for Files<S> {
impl Clone for Files {
fn clone(&self) -> Self {
Self {
directory: self.directory.clone(),
@@ -251,13 +250,13 @@ impl<S> Clone for Files<S> {
}
}
impl<S: 'static> Files<S> {
impl Files {
/// Create new `Files` instance for specified base directory.
///
/// `File` uses `ThreadPool` for blocking filesystem operations.
/// By default pool with 5x threads of available cpus is used.
/// Pool size can be changed by setting ACTIX_CPU_POOL environment variable.
pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files<S> {
pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files {
let dir = dir.into().canonicalize().unwrap_or_else(|_| PathBuf::new());
if !dir.is_dir() {
log::error!("Specified path is not a directory");
@@ -335,7 +334,7 @@ impl<S: 'static> Files<S> {
where
F: IntoNewService<U>,
U: NewService<
Request = ServiceRequest<S>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
> + 'static,
@@ -349,11 +348,8 @@ impl<S: 'static> Files<S> {
}
}
impl<P> HttpServiceFactory<P> for Files<P>
where
P: 'static,
{
fn register(self, config: &mut ServiceConfig<P>) {
impl HttpServiceFactory for Files {
fn register(self, config: &mut ServiceConfig) {
if self.default.borrow().is_none() {
*self.default.borrow_mut() = Some(config.default_service());
}
@@ -366,11 +362,11 @@ where
}
}
impl<P: 'static> NewService for Files<P> {
type Request = ServiceRequest<P>;
impl NewService for Files {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Service = FilesService<P>;
type Service = FilesService;
type InitError = ();
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
@@ -401,22 +397,22 @@ impl<P: 'static> NewService for Files<P> {
}
}
pub struct FilesService<P> {
pub struct FilesService {
directory: PathBuf,
index: Option<String>,
show_index: bool,
default: Option<HttpService<P>>,
default: Option<HttpService>,
renderer: Rc<DirectoryRenderer>,
mime_override: Option<Rc<MimeOverride>>,
file_flags: named::Flags,
}
impl<P> FilesService<P> {
impl FilesService {
fn handle_err(
&mut self,
e: io::Error,
req: HttpRequest,
payload: Payload<P>,
payload: Payload,
) -> Either<
FutureResult<ServiceResponse, Error>,
Box<Future<Item = ServiceResponse, Error = Error>>,
@@ -430,8 +426,8 @@ impl<P> FilesService<P> {
}
}
impl<P> Service for FilesService<P> {
type Request = ServiceRequest<P>;
impl Service for FilesService {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = Either<
@@ -443,7 +439,7 @@ impl<P> Service for FilesService<P> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let (req, pl) = req.into_parts();
let real_path = match PathBufWrp::get_pathbuf(req.match_info().path()) {
@@ -547,11 +543,12 @@ impl PathBufWrp {
}
}
impl<P> FromRequest<P> for PathBufWrp {
impl FromRequest for PathBufWrp {
type Error = UriSegmentError;
type Future = Result<Self, Self::Error>;
type Config = ();
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
PathBufWrp::get_pathbuf(req.match_info().path())
}
}
@@ -570,6 +567,7 @@ mod tests {
self, ContentDisposition, DispositionParam, DispositionType,
};
use actix_web::http::{Method, StatusCode};
use actix_web::middleware::Compress;
use actix_web::test::{self, TestRequest};
use actix_web::App;
@@ -965,7 +963,7 @@ mod tests {
#[test]
fn test_named_file_content_encoding() {
let mut srv = test::init_service(App::new().enable_encoding().service(
let mut srv = test::init_service(App::new().wrap(Compress::default()).service(
web::resource("/").to(|| {
NamedFile::open("Cargo.toml")
.unwrap()
@@ -984,7 +982,7 @@ mod tests {
#[test]
fn test_named_file_content_encoding_gzip() {
let mut srv = test::init_service(App::new().enable_encoding().service(
let mut srv = test::init_service(App::new().wrap(Compress::default()).service(
web::resource("/").to(|| {
NamedFile::open("Cargo.toml")
.unwrap()
@@ -1053,15 +1051,15 @@ mod tests {
#[test]
fn test_static_files_bad_directory() {
let _st: Files<()> = Files::new("/", "missing");
let _st: Files<()> = Files::new("/", "Cargo.toml");
let _st: Files = Files::new("/", "missing");
let _st: Files = Files::new("/", "Cargo.toml");
}
#[test]
fn test_default_handler_file_missing() {
let mut st = test::block_on(
Files::new("/", ".")
.default_handler(|req: ServiceRequest<_>| {
.default_handler(|req: ServiceRequest| {
Ok(req.into_response(HttpResponse::Ok().body("default content")))
})
.new_service(&()),

View File

@@ -15,7 +15,7 @@ use actix_web::http::header::{
self, ContentDisposition, DispositionParam, DispositionType,
};
use actix_web::http::{ContentEncoding, Method, StatusCode};
use actix_web::middleware::encoding::BodyEncoding;
use actix_web::middleware::BodyEncoding;
use actix_web::{Error, HttpMessage, HttpRequest, HttpResponse, Responder};
use crate::range::HttpRange;

View File

@@ -53,6 +53,7 @@ where
type Item = Bytes;
type Error = PayloadError;
#[inline]
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self {
Payload::None => Ok(Async::Ready(None)),

View File

@@ -2,4 +2,6 @@
## [0.1.0-alpha.1] - 2019-04-xx
* Do not support nested multipart
* Split multipart support to separate crate

View File

@@ -16,6 +16,9 @@ pub enum MultipartError {
/// Multipart boundary is not found
#[display(fmt = "Multipart boundary is not found")]
Boundary,
/// Nested multipart is not supported
#[display(fmt = "Nested multipart is not supported")]
Nested,
/// Multipart stream is incomplete
#[display(fmt = "Multipart stream is incomplete")]
Incomplete,

View File

@@ -1,9 +1,5 @@
//! Multipart payload support
use bytes::Bytes;
use futures::Stream;
use actix_web::error::{Error, PayloadError};
use actix_web::{dev::Payload, FromRequest, HttpRequest};
use actix_web::{dev::Payload, Error, FromRequest, HttpRequest};
use crate::server::Multipart;
@@ -21,34 +17,26 @@ use crate::server::Multipart;
///
/// fn index(payload: mp::Multipart) -> impl Future<Item = HttpResponse, Error = Error> {
/// payload.from_err() // <- get multipart stream for current request
/// .and_then(|item| match item { // <- iterate over multipart items
/// mp::Item::Field(field) => {
/// .and_then(|field| { // <- iterate over multipart items
/// // Field in turn is stream of *Bytes* object
/// Either::A(field.from_err()
/// field.from_err()
/// .fold((), |_, chunk| {
/// println!("-- CHUNK: \n{:?}", std::str::from_utf8(&chunk));
/// Ok::<_, Error>(())
/// }))
/// },
/// mp::Item::Nested(mp) => {
/// // Or item could be nested Multipart stream
/// Either::B(ok(()))
/// }
/// })
/// })
/// .fold((), |_, _| Ok::<_, Error>(()))
/// .map(|_| HttpResponse::Ok().into())
/// }
/// # fn main() {}
/// ```
impl<P> FromRequest<P> for Multipart
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
{
impl FromRequest for Multipart {
type Error = Error;
type Future = Result<Multipart, Error>;
type Config = ();
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
Ok(Multipart::new(req.headers(), payload.take()))
}
}

View File

@@ -3,4 +3,4 @@ mod extractor;
mod server;
pub use self::error::MultipartError;
pub use self::server::{Field, Item, Multipart};
pub use self::server::{Field, Multipart};

View File

@@ -32,18 +32,9 @@ pub struct Multipart {
inner: Option<Rc<RefCell<InnerMultipart>>>,
}
/// Multipart item
pub enum Item {
/// Multipart field
Field(Field),
/// Nested multipart stream
Nested(Multipart),
}
enum InnerMultipartItem {
None,
Field(Rc<RefCell<InnerField>>),
Multipart(Rc<RefCell<InnerMultipart>>),
}
#[derive(PartialEq, Debug)]
@@ -113,7 +104,7 @@ impl Multipart {
}
impl Stream for Multipart {
type Item = Item;
type Item = Field;
type Error = MultipartError;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
@@ -245,7 +236,7 @@ impl InnerMultipart {
Ok(Some(eof))
}
fn poll(&mut self, safety: &Safety) -> Poll<Option<Item>, MultipartError> {
fn poll(&mut self, safety: &Safety) -> Poll<Option<Field>, MultipartError> {
if self.state == InnerState::Eof {
Ok(Async::Ready(None))
} else {
@@ -262,14 +253,7 @@ impl InnerMultipart {
Async::Ready(None) => true,
}
}
InnerMultipartItem::Multipart(ref mut multipart) => {
match multipart.borrow_mut().poll(safety)? {
Async::NotReady => return Ok(Async::NotReady),
Async::Ready(Some(_)) => continue,
Async::Ready(None) => true,
}
}
_ => false,
InnerMultipartItem::None => false,
};
if stop {
self.item = InnerMultipartItem::None;
@@ -346,24 +330,7 @@ impl InnerMultipart {
// nested multipart stream
if mt.type_() == mime::MULTIPART {
let inner = if let Some(boundary) = mt.get_param(mime::BOUNDARY) {
Rc::new(RefCell::new(InnerMultipart {
payload: self.payload.clone(),
boundary: boundary.as_str().to_owned(),
state: InnerState::FirstBoundary,
item: InnerMultipartItem::None,
}))
} else {
return Err(MultipartError::Boundary);
};
self.item = InnerMultipartItem::Multipart(Rc::clone(&inner));
Ok(Async::Ready(Some(Item::Nested(Multipart {
safety: safety.clone(),
error: None,
inner: Some(inner),
}))))
Err(MultipartError::Nested)
} else {
let field = Rc::new(RefCell::new(InnerField::new(
self.payload.clone(),
@@ -372,12 +339,12 @@ impl InnerMultipart {
)?));
self.item = InnerMultipartItem::Field(Rc::clone(&field));
Ok(Async::Ready(Some(Item::Field(Field::new(
Ok(Async::Ready(Some(Field::new(
safety.clone(),
headers,
mt,
field,
)))))
))))
}
}
}
@@ -864,16 +831,11 @@ mod tests {
let mut multipart = Multipart::new(&headers, payload);
match multipart.poll().unwrap() {
Async::Ready(Some(item)) => match item {
Item::Field(mut field) => {
{
Async::Ready(Some(mut field)) => {
let cd = field.content_disposition().unwrap();
assert_eq!(cd.disposition, DispositionType::FormData);
assert_eq!(
cd.parameters[0],
DispositionParam::Name("file".into())
);
}
assert_eq!(cd.parameters[0], DispositionParam::Name("file".into()));
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
@@ -887,13 +849,10 @@ mod tests {
}
}
_ => unreachable!(),
},
_ => unreachable!(),
}
match multipart.poll().unwrap() {
Async::Ready(Some(item)) => match item {
Item::Field(mut field) => {
Async::Ready(Some(mut field)) => {
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
@@ -907,8 +866,6 @@ mod tests {
}
}
_ => unreachable!(),
},
_ => unreachable!(),
}
match multipart.poll().unwrap() {

View File

@@ -1,5 +1,9 @@
# Changes
## [0.1.0-alpha.6] - 2019-04-14
* Update actix-web alpha.6
## [0.1.0-alpha.4] - 2019-04-08
* Update actix-web

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-session"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.6"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Session for actix web framework."
readme = "README.md"
@@ -24,7 +24,7 @@ default = ["cookie-session"]
cookie-session = ["actix-web/secure-cookies"]
[dependencies]
actix-web = "1.0.0-alpha.5"
actix-web = "1.0.0-alpha.6"
actix-service = "0.3.4"
bytes = "0.4"
derive_more = "0.14"

View File

@@ -120,7 +120,7 @@ impl CookieSessionInner {
Ok(())
}
fn load<P>(&self, req: &ServiceRequest<P>) -> HashMap<String, String> {
fn load(&self, req: &ServiceRequest) -> HashMap<String, String> {
if let Ok(cookies) = req.cookies() {
for cookie in cookies.iter() {
if cookie.name() == self.name {
@@ -256,13 +256,13 @@ impl CookieSession {
}
}
impl<S, P, B: 'static> Transform<S> for CookieSession
impl<S, B: 'static> Transform<S> for CookieSession
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
S::Error: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type InitError = ();
@@ -283,13 +283,13 @@ pub struct CookieSessionMiddleware<S> {
inner: Rc<CookieSessionInner>,
}
impl<S, P, B: 'static> Service for CookieSessionMiddleware<S>
impl<S, B: 'static> Service for CookieSessionMiddleware<S>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
S::Error: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
@@ -298,7 +298,7 @@ where
self.service.poll_ready()
}
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let inner = self.inner.clone();
let state = self.inner.load(&req);
Session::set_session(state.into_iter(), &mut req);

View File

@@ -119,9 +119,9 @@ impl Session {
inner.state.clear()
}
pub fn set_session<P>(
pub fn set_session(
data: impl Iterator<Item = (String, String)>,
req: &mut ServiceRequest<P>,
req: &mut ServiceRequest,
) {
let session = Session::get_session(&mut *req.extensions_mut());
let mut inner = session.0.borrow_mut();
@@ -172,12 +172,13 @@ impl Session {
/// }
/// # fn main() {}
/// ```
impl<P> FromRequest<P> for Session {
impl FromRequest for Session {
type Error = Error;
type Future = Result<Session, Error>;
type Config = ();
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
Ok(Session::get_session(&mut *req.extensions_mut()))
}
}

View File

@@ -1,5 +1,9 @@
# Changes
## [0.1.0-alpha.6] - 2019-04-14
* Gen code for actix-web 1.0.0-alpha.6
## [0.1.0-alpha.1] - 2019-03-28
* Initial impl

View File

@@ -1,6 +1,6 @@
[package]
name = "actix-web-codegen"
version = "0.1.0-alpha.1"
version = "0.1.0-alpha.6"
description = "Actix web proc macros"
readme = "README.md"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
@@ -16,7 +16,7 @@ quote = "0.6"
syn = { version = "0.15", features = ["full", "parsing"] }
[dev-dependencies]
actix-web = { version = "1.0.0-alpha.5" }
actix-web = { version = "1.0.0-alpha.6" }
actix-http = { version = "0.1.0-alpha.5", features=["ssl"] }
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
futures = { version = "0.1" }

View File

@@ -61,8 +61,8 @@ impl fmt::Display for Args {
#[allow(non_camel_case_types)]
pub struct {name};
impl<P: 'static> actix_web::dev::HttpServiceFactory<P> for {name} {{
fn register(self, config: &mut actix_web::dev::ServiceConfig<P>) {{
impl actix_web::dev::HttpServiceFactory for {name} {{
fn register(self, config: &mut actix_web::dev::ServiceConfig) {{
{ast}
let resource = actix_web::Resource::new(\"{path}\"){guards}.{to}({name});

View File

@@ -4,11 +4,6 @@ use actix_web::{http, App, HttpResponse, Responder};
use actix_web_codegen::get;
use futures::{future, Future};
//fn guard_head(head: &actix_web::dev::RequestHead) -> bool {
// true
//}
//#[get("/test", guard="guard_head")]
#[get("/test")]
fn test() -> impl Responder {
HttpResponse::Ok()

View File

@@ -1,5 +1,12 @@
# Changes
## [0.1.0-alpha.6] - 2019-04-14
### Changed
* Do not set default headers for websocket request
## [0.1.0-alpha.5] - 2019-04-12
### Changed

View File

@@ -1,6 +1,6 @@
[package]
name = "awc"
version = "0.1.0-alpha.5"
version = "0.1.0-alpha.6"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix http client."
readme = "README.md"
@@ -55,7 +55,7 @@ openssl = { version="0.10", optional = true }
[dev-dependencies]
actix-rt = "0.2.2"
actix-web = { version = "1.0.0-alpha.5", features=["ssl"] }
actix-web = { version = "1.0.0-alpha.6", features=["ssl"] }
actix-http = { version = "0.1.0-alpha.5", features=["ssl"] }
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
actix-utils = "0.3.4"

View File

@@ -545,21 +545,18 @@ impl fmt::Debug for ClientRequest {
#[cfg(test)]
mod tests {
use super::*;
use crate::{test, Client};
use crate::Client;
#[test]
fn test_debug() {
test::run_on(|| {
let request = Client::new().get("/").header("x-test", "111");
let repr = format!("{:?}", request);
assert!(repr.contains("ClientRequest"));
assert!(repr.contains("x-test"));
})
}
#[test]
fn test_client_header() {
test::run_on(|| {
let req = Client::build()
.header(header::CONTENT_TYPE, "111")
.finish()
@@ -574,12 +571,10 @@ mod tests {
.unwrap(),
"111"
);
})
}
#[test]
fn test_client_header_override() {
test::run_on(|| {
let req = Client::build()
.header(header::CONTENT_TYPE, "111")
.finish()
@@ -595,12 +590,10 @@ mod tests {
.unwrap(),
"222"
);
})
}
#[test]
fn client_basic_auth() {
test::run_on(|| {
let req = Client::new()
.get("/")
.basic_auth("username", Some("password"));
@@ -624,12 +617,10 @@ mod tests {
.unwrap(),
"Basic dXNlcm5hbWU="
);
});
}
#[test]
fn client_bearer_auth() {
test::run_on(|| {
let req = Client::new().get("/").bearer_auth("someS3cr3tAutht0k3n");
assert_eq!(
req.head
@@ -640,6 +631,5 @@ mod tests {
.unwrap(),
"Bearer someS3cr3tAutht0k3n"
);
})
}
}

View File

@@ -1,13 +1,11 @@
//! Websockets client
use std::fmt::Write as FmtWrite;
use std::io::Write;
use std::rc::Rc;
use std::{fmt, str};
use actix_codec::Framed;
use actix_http::cookie::{Cookie, CookieJar};
use actix_http::{ws, Payload, RequestHead};
use bytes::{BufMut, BytesMut};
use futures::future::{err, Either, Future};
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
use tokio_timer::Timeout;
@@ -33,7 +31,6 @@ pub struct WebsocketsRequest {
protocols: Option<String>,
max_size: usize,
server_mode: bool,
default_headers: bool,
cookies: Option<CookieJar>,
config: Rc<ClientConfig>,
}
@@ -63,7 +60,6 @@ impl WebsocketsRequest {
max_size: 65_536,
server_mode: false,
cookies: None,
default_headers: true,
}
}
@@ -119,13 +115,6 @@ impl WebsocketsRequest {
self
}
/// Do not add default request headers.
/// By default `Date` and `User-Agent` headers are set.
pub fn no_default_headers(mut self) -> Self {
self.default_headers = false;
self
}
/// Append a header.
///
/// Header gets appended to existing header.
@@ -188,10 +177,9 @@ impl WebsocketsRequest {
}
/// Set HTTP basic authorization header
pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> Self
pub fn basic_auth<U>(self, username: U, password: Option<&str>) -> Self
where
U: fmt::Display,
P: fmt::Display,
{
let auth = match password {
Some(password) => format!("{}:{}", username, password),
@@ -232,67 +220,36 @@ impl WebsocketsRequest {
return Either::A(err(InvalidUrl::UnknownScheme.into()));
}
// set default headers
let mut slf = if self.default_headers {
// set request host header
if let Some(host) = self.head.uri.host() {
if !self.head.headers.contains_key(&header::HOST) {
let mut wrt = BytesMut::with_capacity(host.len() + 5).writer();
let _ = match self.head.uri.port_u16() {
None | Some(80) | Some(443) => write!(wrt, "{}", host),
Some(port) => write!(wrt, "{}:{}", host, port),
};
match wrt.get_mut().take().freeze().try_into() {
Ok(value) => {
self.head.headers.insert(header::HOST, value);
}
Err(e) => return Either::A(err(HttpError::from(e).into())),
}
}
}
// user agent
self.set_header_if_none(
header::USER_AGENT,
concat!("awc/", env!("CARGO_PKG_VERSION")),
)
} else {
self
};
let mut head = slf.head;
// set cookies
if let Some(ref mut jar) = slf.cookies {
if let Some(ref mut jar) = self.cookies {
let mut cookie = String::new();
for c in jar.delta() {
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
let _ = write!(&mut cookie, "; {}={}", name, value);
}
head.headers.insert(
self.head.headers.insert(
header::COOKIE,
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
);
}
// origin
if let Some(origin) = slf.origin.take() {
head.headers.insert(header::ORIGIN, origin);
if let Some(origin) = self.origin.take() {
self.head.headers.insert(header::ORIGIN, origin);
}
head.set_connection_type(ConnectionType::Upgrade);
head.headers
self.head.set_connection_type(ConnectionType::Upgrade);
self.head
.headers
.insert(header::UPGRADE, HeaderValue::from_static("websocket"));
head.headers.insert(
self.head.headers.insert(
header::SEC_WEBSOCKET_VERSION,
HeaderValue::from_static("13"),
);
if let Some(protocols) = slf.protocols.take() {
head.headers.insert(
if let Some(protocols) = self.protocols.take() {
self.head.headers.insert(
header::SEC_WEBSOCKET_PROTOCOL,
HeaderValue::try_from(protocols.as_str()).unwrap(),
);
@@ -304,15 +261,16 @@ impl WebsocketsRequest {
let sec_key: [u8; 16] = rand::random();
let key = base64::encode(&sec_key);
head.headers.insert(
self.head.headers.insert(
header::SEC_WEBSOCKET_KEY,
HeaderValue::try_from(key.as_str()).unwrap(),
);
let max_size = slf.max_size;
let server_mode = slf.server_mode;
let head = self.head;
let max_size = self.max_size;
let server_mode = self.server_mode;
let fut = slf
let fut = self
.config
.connector
.borrow_mut()
@@ -387,7 +345,7 @@ impl WebsocketsRequest {
});
// set request timeout
if let Some(timeout) = slf.config.timeout {
if let Some(timeout) = self.config.timeout {
Either::B(Either::A(Timeout::new(fut, timeout).map_err(|e| {
if let Some(e) = e.into_inner() {
e
@@ -400,3 +358,107 @@ impl WebsocketsRequest {
}
}
}
impl fmt::Debug for WebsocketsRequest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
"\nWebsocketsRequest {}:{}",
self.head.method, self.head.uri
)?;
writeln!(f, " headers:")?;
for (key, val) in self.head.headers.iter() {
writeln!(f, " {:?}: {:?}", key, val)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Client;
#[test]
fn test_debug() {
let request = Client::new().ws("/").header("x-test", "111");
let repr = format!("{:?}", request);
assert!(repr.contains("WebsocketsRequest"));
assert!(repr.contains("x-test"));
}
#[test]
fn test_header_override() {
let req = Client::build()
.header(header::CONTENT_TYPE, "111")
.finish()
.ws("/")
.set_header(header::CONTENT_TYPE, "222");
assert_eq!(
req.head
.headers
.get(header::CONTENT_TYPE)
.unwrap()
.to_str()
.unwrap(),
"222"
);
}
#[test]
fn basic_auth() {
let req = Client::new()
.ws("/")
.basic_auth("username", Some("password"));
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Basic dXNlcm5hbWU6cGFzc3dvcmQ="
);
let req = Client::new().ws("/").basic_auth("username", None);
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Basic dXNlcm5hbWU="
);
}
#[test]
fn bearer_auth() {
let req = Client::new().ws("/").bearer_auth("someS3cr3tAutht0k3n");
assert_eq!(
req.head
.headers
.get(header::AUTHORIZATION)
.unwrap()
.to_str()
.unwrap(),
"Bearer someS3cr3tAutht0k3n"
);
}
#[test]
fn basics() {
let req = Client::new()
.ws("/")
.origin("test-origin")
.max_frame_size(100)
.server_mode()
.protocols(&["v1", "v2"])
.cookie(Cookie::build("cookie1", "value1").finish());
assert_eq!(req.origin.unwrap().to_str().unwrap(), "test-origin");
assert_eq!(req.max_size, 100);
assert_eq!(req.server_mode, true);
assert_eq!(req.protocols, Some("v1,v2".to_string()));
}
}

View File

@@ -10,6 +10,7 @@ use rand::Rng;
use actix_http::HttpService;
use actix_http_test::TestServer;
use actix_web::http::Cookie;
use actix_web::{http::header, web, App, Error, HttpMessage, HttpRequest, HttpResponse};
use awc::error::SendRequestError;
@@ -406,7 +407,6 @@ fn test_client_brotli_encoding() {
#[test]
fn test_client_cookie_handling() {
use actix_web::http::Cookie;
fn err() -> Error {
use std::io::{Error as IoError, ErrorKind};
// stub some generic error
@@ -468,36 +468,6 @@ fn test_client_cookie_handling() {
assert_eq!(c2, cookie2);
}
// #[test]
// fn test_default_headers() {
// let srv = test::TestServer::new(|app| app.handler(|_| HttpResponse::Ok().body(STR)));
// let request = srv.get("/").finish().unwrap();
// let repr = format!("{:?}", request);
// assert!(repr.contains("\"accept-encoding\": \"gzip, deflate\""));
// assert!(repr.contains(concat!(
// "\"user-agent\": \"actix-web/",
// env!("CARGO_PKG_VERSION"),
// "\""
// )));
// let request_override = srv
// .get("/")
// .header("User-Agent", "test")
// .header("Accept-Encoding", "over_test")
// .finish()
// .unwrap();
// let repr_override = format!("{:?}", request_override);
// assert!(repr_override.contains("\"user-agent\": \"test\""));
// assert!(repr_override.contains("\"accept-encoding\": \"over_test\""));
// assert!(!repr_override.contains("\"accept-encoding\": \"gzip, deflate\""));
// assert!(!repr_override.contains(concat!(
// "\"user-agent\": \"Actix-web/",
// env!("CARGO_PKG_VERSION"),
// "\""
// )));
// }
// #[test]
// fn client_read_until_eof() {
// let addr = test::TestServer::unused_addr();

View File

@@ -27,7 +27,7 @@ fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.wrap(middleware::encoding::Compress::default())
.wrap(middleware::Compress::default())
.wrap(middleware::Logger::default())
.service(index)
.service(no_params)
@@ -36,9 +36,9 @@ fn main() -> std::io::Result<()> {
.wrap(
middleware::DefaultHeaders::new().header("X-Version-R2", "0.3"),
)
.default_resource(|r| {
r.route(web::route().to(|| HttpResponse::MethodNotAllowed()))
})
.default_service(
web::route().to(|| HttpResponse::MethodNotAllowed()),
)
.route(web::get().to_async(index_async)),
)
.service(web::resource("/test1.html").to(|| "Test\r\n"))

View File

@@ -1,24 +1,21 @@
use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::rc::Rc;
use actix_http::body::{Body, MessageBody};
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
use actix_http::encoding::{Decoder, Encoder};
use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService};
use actix_service::{
apply_transform, IntoNewService, IntoTransform, NewService, Transform,
};
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
use bytes::Bytes;
use futures::{IntoFuture, Stream};
use futures::IntoFuture;
use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory};
use crate::app_service::{AppEntry, AppInit, AppRoutingFactory};
use crate::config::{AppConfig, AppConfigInner, RouterConfig};
use crate::data::{Data, DataFactory};
use crate::dev::{Payload, PayloadStream, ResourceDef};
use crate::error::{Error, PayloadError};
use crate::dev::ResourceDef;
use crate::error::Error;
use crate::resource::Resource;
use crate::route::Route;
use crate::service::{
@@ -26,40 +23,44 @@ use crate::service::{
ServiceResponse,
};
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
/// Application builder - structure that follows the builder pattern
/// for building application instances.
pub struct App<In, Out, T>
where
T: NewService<Request = ServiceRequest<In>, Response = ServiceRequest<Out>>,
{
chain: T,
pub struct App<T, B> {
endpoint: T,
services: Vec<Box<ServiceFactory>>,
default: Option<Rc<HttpNewService>>,
factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
data: Vec<Box<DataFactory>>,
config: AppConfigInner,
_t: PhantomData<(In, Out)>,
external: Vec<ResourceDef>,
_t: PhantomData<(B)>,
}
impl App<PayloadStream, PayloadStream, AppChain> {
impl App<AppEntry, Body> {
/// Create application builder. Application can be configured with a builder-like pattern.
pub fn new() -> Self {
let fref = Rc::new(RefCell::new(None));
App {
chain: AppChain,
endpoint: AppEntry::new(fref.clone()),
data: Vec::new(),
services: Vec::new(),
default: None,
factory_ref: fref,
config: AppConfigInner::default(),
external: Vec::new(),
_t: PhantomData,
}
}
}
impl<In, Out, T> App<In, Out, T>
impl<T, B> App<T, B>
where
In: 'static,
Out: 'static,
B: MessageBody,
T: NewService<
Request = ServiceRequest<In>,
Response = ServiceRequest<Out>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
@@ -112,151 +113,6 @@ where
self
}
/// Registers middleware, in the form of a middleware component (type),
/// that runs during inbound and/or outbound processing in the request
/// lifecycle (request -> response), modifying request/response as
/// necessary, across all requests managed by the *Application*.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
///
/// ```rust
/// use actix_service::Service;
/// # use futures::Future;
/// use actix_web::{middleware, web, App};
/// use actix_web::http::{header::CONTENT_TYPE, HeaderValue};
///
/// fn index() -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap(middleware::Logger::default())
/// .route("/index.html", web::get().to(index));
/// }
/// ```
pub fn wrap<M, B, F>(
self,
mw: F,
) -> AppRouter<
T,
Out,
B,
impl NewService<
Request = ServiceRequest<Out>,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
>
where
M: Transform<
AppRouting<Out>,
Request = ServiceRequest<Out>,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
F: IntoTransform<M, AppRouting<Out>>,
{
let fref = Rc::new(RefCell::new(None));
let endpoint = apply_transform(mw, AppEntry::new(fref.clone()));
AppRouter {
endpoint,
chain: self.chain,
data: self.data,
services: Vec::new(),
default: None,
factory_ref: fref,
config: self.config,
external: Vec::new(),
_t: PhantomData,
}
}
/// Registers middleware, in the form of a closure, that runs during inbound
/// and/or outbound processing in the request lifecycle (request -> response),
/// modifying request/response as necessary, across all requests managed by
/// the *Application*.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
///
/// ```rust
/// use actix_service::Service;
/// # use futures::Future;
/// use actix_web::{web, App};
/// use actix_web::http::{header::CONTENT_TYPE, HeaderValue};
///
/// fn index() -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap_fn(|req, srv|
/// srv.call(req).map(|mut res| {
/// res.headers_mut().insert(
/// CONTENT_TYPE, HeaderValue::from_static("text/plain"),
/// );
/// res
/// }))
/// .route("/index.html", web::get().to(index));
/// }
/// ```
pub fn wrap_fn<F, R, B>(
self,
mw: F,
) -> AppRouter<
T,
Out,
B,
impl NewService<
Request = ServiceRequest<Out>,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
>
where
F: FnMut(ServiceRequest<Out>, &mut AppRouting<Out>) -> R + Clone,
R: IntoFuture<Item = ServiceResponse<B>, Error = Error>,
{
self.wrap(mw)
}
/// Register a request modifier. It can modify any request parameters
/// including request payload type.
pub fn chain<C, F, P>(
self,
chain: F,
) -> App<
In,
P,
impl NewService<
Request = ServiceRequest<In>,
Response = ServiceRequest<P>,
Error = Error,
InitError = (),
>,
>
where
C: NewService<
Request = ServiceRequest<Out>,
Response = ServiceRequest<P>,
Error = Error,
InitError = (),
>,
F: IntoNewService<C>,
{
let chain = self.chain.and_then(chain.into_new_service());
App {
chain,
data: self.data,
config: self.config,
_t: PhantomData,
}
}
/// Run external configuration as part of the application building
/// process
///
@@ -269,7 +125,7 @@ where
/// use actix_web::{web, middleware, App, HttpResponse};
///
/// // this function could be located in different module
/// fn config<P>(cfg: &mut web::RouterConfig<P>) {
/// fn config(cfg: &mut web::RouterConfig) {
/// cfg.service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
@@ -283,27 +139,16 @@ where
/// .route("/index.html", web::get().to(|| HttpResponse::Ok()));
/// }
/// ```
pub fn configure<F>(mut self, f: F) -> AppRouter<T, Out, Body, AppEntry<Out>>
pub fn configure<F>(mut self, f: F) -> Self
where
F: Fn(&mut RouterConfig<Out>),
F: Fn(&mut RouterConfig),
{
let mut cfg = RouterConfig::new();
f(&mut cfg);
self.data.extend(cfg.data);
let fref = Rc::new(RefCell::new(None));
AppRouter {
chain: self.chain,
default: None,
endpoint: AppEntry::new(fref.clone()),
factory_ref: fref,
data: self.data,
config: self.config,
services: cfg.services,
external: cfg.external,
_t: PhantomData,
}
self.services.extend(cfg.services);
self.external.extend(cfg.external);
self
}
/// Configure route for a specific path.
@@ -325,171 +170,7 @@ where
/// .route("/test2", web::post().to(|| HttpResponse::MethodNotAllowed()));
/// }
/// ```
pub fn route(
self,
path: &str,
mut route: Route<Out>,
) -> AppRouter<T, Out, Body, AppEntry<Out>> {
self.service(
Resource::new(path)
.add_guards(route.take_guards())
.route(route),
)
}
/// Register http service.
///
/// Http service is any type that implements `HttpServiceFactory` trait.
///
/// Actix web provides several services implementations:
///
/// * *Resource* is an entry in resource table which corresponds to requested URL.
/// * *Scope* is a set of resources with common root path.
/// * "StaticFiles" is a service for static files support
pub fn service<F>(self, service: F) -> AppRouter<T, Out, Body, AppEntry<Out>>
where
F: HttpServiceFactory<Out> + 'static,
{
let fref = Rc::new(RefCell::new(None));
AppRouter {
chain: self.chain,
default: None,
endpoint: AppEntry::new(fref.clone()),
factory_ref: fref,
data: self.data,
config: self.config,
services: vec![Box::new(ServiceFactoryWrapper::new(service))],
external: Vec::new(),
_t: PhantomData,
}
}
/// Set server host name.
///
/// Host name is used by application router as a hostname for url
/// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo.
/// html#method.host) documentation for more information.
///
/// By default host name is set to a "localhost" value.
pub fn hostname(mut self, val: &str) -> Self {
self.config.host = val.to_owned();
self
}
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
/// Enable content compression and decompression.
pub fn enable_encoding(
self,
) -> AppRouter<
impl NewService<
Request = ServiceRequest<In>,
Response = ServiceRequest<Decoder<Payload<Out>>>,
Error = Error,
InitError = (),
>,
Decoder<Payload<Out>>,
Encoder<Body>,
impl NewService<
Request = ServiceRequest<Decoder<Payload<Out>>>,
Response = ServiceResponse<Encoder<Body>>,
Error = Error,
InitError = (),
>,
>
where
Out: Stream<Item = Bytes, Error = PayloadError>,
{
use crate::middleware::encoding::{Compress, Decompress};
self.chain(Decompress::new()).wrap(Compress::default())
}
}
/// Application router builder - Structure that follows the builder pattern
/// for building application instances.
pub struct AppRouter<C, P, B, T> {
chain: C,
endpoint: T,
services: Vec<Box<ServiceFactory<P>>>,
default: Option<Rc<HttpNewService<P>>>,
factory_ref: Rc<RefCell<Option<AppRoutingFactory<P>>>>,
data: Vec<Box<DataFactory>>,
config: AppConfigInner,
external: Vec<ResourceDef>,
_t: PhantomData<(P, B)>,
}
impl<C, P, B, T> AppRouter<C, P, B, T>
where
P: 'static,
B: MessageBody,
T: NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
{
/// Run external configuration as part of the application building
/// process
///
/// This function is useful for moving parts of configuration to a
/// different module or even library. For example,
/// some of the resource's configuration could be moved to different module.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{web, middleware, App, HttpResponse};
///
/// // this function could be located in different module
/// fn config<P>(cfg: &mut web::RouterConfig<P>) {
/// cfg.service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
/// );
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap(middleware::Logger::default())
/// .configure(config) // <- register resources
/// .route("/index.html", web::get().to(|| HttpResponse::Ok()));
/// }
/// ```
pub fn configure<F>(mut self, f: F) -> Self
where
F: Fn(&mut RouterConfig<P>),
{
let mut cfg = RouterConfig::new();
f(&mut cfg);
self.data.extend(cfg.data);
self.services.extend(cfg.services);
self.external.extend(cfg.external);
self
}
/// Configure route for a specific path.
///
/// This is a simplified version of the `App::service()` method.
/// This method can not be could multiple times, in that case
/// multiple resources with one route would be registered for same resource path.
///
/// ```rust
/// use actix_web::{web, App, HttpResponse};
///
/// fn index(data: web::Path<(String, String)>) -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .route("/test1", web::get().to(index))
/// .route("/test2", web::post().to(|| HttpResponse::MethodNotAllowed()));
/// }
/// ```
pub fn route(self, path: &str, mut route: Route<P>) -> Self {
pub fn route(self, path: &str, mut route: Route) -> Self {
self.service(
Resource::new(path)
.add_guards(route.take_guards())
@@ -508,102 +189,75 @@ where
/// * "StaticFiles" is a service for static files support
pub fn service<F>(mut self, factory: F) -> Self
where
F: HttpServiceFactory<P> + 'static,
F: HttpServiceFactory + 'static,
{
self.services
.push(Box::new(ServiceFactoryWrapper::new(factory)));
self
}
/// Registers middleware, in the form of a middleware component (type),
/// that runs during inbound and/or outbound processing in the request
/// lifecycle (request -> response), modifying request/response as
/// necessary, across all requests managed by the *Route*.
/// Set server host name.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
/// Host name is used by application router as a hostname for url
/// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo.
/// html#method.host) documentation for more information.
///
pub fn wrap<M, B1, F>(
self,
mw: F,
) -> AppRouter<
C,
P,
B1,
impl NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
>
where
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
B1: MessageBody,
F: IntoTransform<M, T::Service>,
{
let endpoint = apply_transform(mw, self.endpoint);
AppRouter {
endpoint,
chain: self.chain,
data: self.data,
services: self.services,
default: self.default,
factory_ref: self.factory_ref,
config: self.config,
external: self.external,
_t: PhantomData,
}
/// By default host name is set to a "localhost" value.
pub fn hostname(mut self, val: &str) -> Self {
self.config.host = val.to_owned();
self
}
/// Registers middleware, in the form of a closure, that runs during inbound
/// and/or outbound processing in the request lifecycle (request -> response),
/// modifying request/response as necessary, across all requests managed by
/// the *Route*.
/// Default service to be used if no matching resource could be found.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
/// It is possible to use services like `Resource`, `Route`.
///
pub fn wrap_fn<B1, F, R>(
self,
mw: F,
) -> AppRouter<
C,
P,
B1,
impl NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
>
/// ```rust
/// use actix_web::{web, App, HttpResponse};
///
/// fn index() -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .service(
/// web::resource("/index.html").route(web::get().to(index)))
/// .default_service(
/// web::route().to(|| HttpResponse::NotFound()));
/// }
/// ```
///
/// It is also possible to use static files as default service.
///
/// ```rust
/// use actix_files::Files;
/// use actix_web::{web, App, HttpResponse};
///
/// fn main() {
/// let app = App::new()
/// .service(
/// web::resource("/index.html").to(|| HttpResponse::Ok()))
/// .default_service(
/// Files::new("", "./static")
/// );
/// }
/// ```
pub fn default_service<F, U>(mut self, f: F) -> Self
where
B1: MessageBody,
F: FnMut(ServiceRequest<P>, &mut T::Service) -> R + Clone,
R: IntoFuture<Item = ServiceResponse<B1>, Error = Error>,
{
self.wrap(mw)
}
/// Default resource to be used if no matching resource could be found.
pub fn default_resource<F, U>(mut self, f: F) -> Self
where
F: FnOnce(Resource<P>) -> Resource<P, U>,
F: IntoNewService<U>,
U: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
> + 'static,
U::InitError: fmt::Debug,
{
// create and configure default resource
self.default = Some(Rc::new(boxed::new_service(
f(Resource::new("")).into_new_service().map_init_err(|_| ()),
f.into_new_service().map_init_err(|e| {
log::error!("Can not construct default service: {:?}", e)
}),
)));
self
@@ -641,27 +295,128 @@ where
self.external.push(rdef);
self
}
/// Registers middleware, in the form of a middleware component (type),
/// that runs during inbound and/or outbound processing in the request
/// lifecycle (request -> response), modifying request/response as
/// necessary, across all requests managed by the *Application*.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
///
/// ```rust
/// use actix_service::Service;
/// # use futures::Future;
/// use actix_web::{middleware, web, App};
/// use actix_web::http::{header::CONTENT_TYPE, HeaderValue};
///
/// fn index() -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap(middleware::Logger::default())
/// .route("/index.html", web::get().to(index));
/// }
/// ```
pub fn wrap<M, B1, F>(
self,
mw: F,
) -> App<
impl NewService<
Request = ServiceRequest,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
B1,
>
where
M: Transform<
T::Service,
Request = ServiceRequest,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
B1: MessageBody,
F: IntoTransform<M, T::Service>,
{
let endpoint = apply_transform(mw, self.endpoint);
App {
endpoint,
data: self.data,
services: self.services,
default: self.default,
factory_ref: self.factory_ref,
config: self.config,
external: self.external,
_t: PhantomData,
}
}
/// Registers middleware, in the form of a closure, that runs during inbound
/// and/or outbound processing in the request lifecycle (request -> response),
/// modifying request/response as necessary, across all requests managed by
/// the *Application*.
///
/// Use middleware when you need to read or modify *every* request or response in some way.
///
/// ```rust
/// use actix_service::Service;
/// # use futures::Future;
/// use actix_web::{web, App};
/// use actix_web::http::{header::CONTENT_TYPE, HeaderValue};
///
/// fn index() -> &'static str {
/// "Welcome!"
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap_fn(|req, srv|
/// srv.call(req).map(|mut res| {
/// res.headers_mut().insert(
/// CONTENT_TYPE, HeaderValue::from_static("text/plain"),
/// );
/// res
/// }))
/// .route("/index.html", web::get().to(index));
/// }
/// ```
pub fn wrap_fn<B1, F, R>(
self,
mw: F,
) -> App<
impl NewService<
Request = ServiceRequest,
Response = ServiceResponse<B1>,
Error = Error,
InitError = (),
>,
B1,
>
where
B1: MessageBody,
F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone,
R: IntoFuture<Item = ServiceResponse<B1>, Error = Error>,
{
self.wrap(mw)
}
}
impl<C, T, P: 'static, B: MessageBody> IntoNewService<AppInit<C, T, P, B>, ServerConfig>
for AppRouter<C, P, B, T>
impl<T, B> IntoNewService<AppInit<T, B>, ServerConfig> for App<T, B>
where
B: MessageBody,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
C: NewService<
Request = ServiceRequest,
Response = ServiceRequest<P>,
Error = Error,
InitError = (),
>,
{
fn into_new_service(self) -> AppInit<C, T, P, B> {
fn into_new_service(self) -> AppInit<T, B> {
AppInit {
chain: self.chain,
data: self.data,
endpoint: self.endpoint,
services: RefCell::new(self.services),
@@ -702,10 +457,14 @@ mod tests {
.service(web::resource("/test").to(|| HttpResponse::Ok()))
.service(
web::resource("/test2")
.default_resource(|r| r.to(|| HttpResponse::Created()))
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::Created())
})
.route(web::get().to(|| HttpResponse::Ok())),
)
.default_resource(|r| r.to(|| HttpResponse::MethodNotAllowed())),
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::MethodNotAllowed())
}),
);
let req = TestRequest::with_uri("/blah").to_request();
@@ -742,13 +501,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
fn md<S, P, B>(
req: ServiceRequest<P>,
fn md<S, B>(
req: ServiceRequest,
srv: &mut S,
) -> impl IntoFuture<Item = ServiceResponse<B>, Error = Error>
where
S: Service<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
>,

View File

@@ -6,7 +6,7 @@ use actix_http::{Request, Response};
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{fn_service, AndThen, NewService, Service, ServiceExt};
use actix_service::{fn_service, NewService, Service};
use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, Poll};
@@ -19,9 +19,8 @@ use crate::rmap::ResourceMap;
use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse};
type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
type BoxedResponse = Either<
FutureResult<ServiceResponse, Error>,
Box<Future<Item = ServiceResponse, Error = Error>>,
@@ -29,36 +28,28 @@ type BoxedResponse = Either<
/// Service factory to convert `Request` to a `ServiceRequest<S>`.
/// It also executes data factories.
pub struct AppInit<C, T, P, B>
pub struct AppInit<T, B>
where
C: NewService<Request = ServiceRequest, Response = ServiceRequest<P>>,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
{
pub(crate) chain: C,
pub(crate) endpoint: T,
pub(crate) data: Vec<Box<DataFactory>>,
pub(crate) config: RefCell<AppConfig>,
pub(crate) services: RefCell<Vec<Box<ServiceFactory<P>>>>,
pub(crate) default: Option<Rc<HttpNewService<P>>>,
pub(crate) factory_ref: Rc<RefCell<Option<AppRoutingFactory<P>>>>,
pub(crate) services: RefCell<Vec<Box<ServiceFactory>>>,
pub(crate) default: Option<Rc<HttpNewService>>,
pub(crate) factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
pub(crate) external: RefCell<Vec<ResourceDef>>,
}
impl<C, T, P: 'static, B> NewService<ServerConfig> for AppInit<C, T, P, B>
impl<T, B> NewService<ServerConfig> for AppInit<T, B>
where
C: NewService<
Request = ServiceRequest,
Response = ServiceRequest<P>,
Error = Error,
InitError = (),
>,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
@@ -66,15 +57,15 @@ where
{
type Request = Request;
type Response = ServiceResponse<B>;
type Error = C::Error;
type InitError = C::InitError;
type Service = AndThen<AppInitService<C::Service, P>, T::Service>;
type Future = AppInitResult<C, T, P, B>;
type Error = T::Error;
type InitError = T::InitError;
type Service = AppInitService<T::Service, B>;
type Future = AppInitResult<T, B>;
fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
// update resource default service
let default = self.default.clone().unwrap_or_else(|| {
Rc::new(boxed::new_service(fn_service(|req: ServiceRequest<P>| {
Rc::new(boxed::new_service(fn_service(|req: ServiceRequest| {
Ok(req.into_response(Response::NotFound().finish()))
})))
});
@@ -121,8 +112,6 @@ where
rmap.finish(rmap.clone());
AppInitResult {
chain: None,
chain_fut: self.chain.new_service(&()),
endpoint: None,
endpoint_fut: self.endpoint.new_service(&()),
data: self.data.iter().map(|s| s.construct()).collect(),
@@ -133,38 +122,29 @@ where
}
}
pub struct AppInitResult<C, T, P, B>
pub struct AppInitResult<T, B>
where
C: NewService,
T: NewService,
{
chain: Option<C::Service>,
endpoint: Option<T::Service>,
chain_fut: C::Future,
endpoint_fut: T::Future,
rmap: Rc<ResourceMap>,
data: Vec<Box<DataFactoryResult>>,
config: AppConfig,
_t: PhantomData<(P, B)>,
_t: PhantomData<B>,
}
impl<C, T, P, B> Future for AppInitResult<C, T, P, B>
impl<T, B> Future for AppInitResult<T, B>
where
C: NewService<
Request = ServiceRequest,
Response = ServiceRequest<P>,
Error = Error,
InitError = (),
>,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
{
type Item = AndThen<AppInitService<C::Service, P>, T::Service>;
type Error = C::InitError;
type Item = AppInitService<T::Service, B>;
type Error = T::InitError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut idx = 0;
@@ -177,28 +157,19 @@ where
}
}
if self.chain.is_none() {
if let Async::Ready(srv) = self.chain_fut.poll()? {
self.chain = Some(srv);
}
}
if self.endpoint.is_none() {
if let Async::Ready(srv) = self.endpoint_fut.poll()? {
self.endpoint = Some(srv);
}
}
if self.chain.is_some() && self.endpoint.is_some() {
Ok(Async::Ready(
AppInitService {
chain: self.chain.take().unwrap(),
if self.endpoint.is_some() {
Ok(Async::Ready(AppInitService {
service: self.endpoint.take().unwrap(),
rmap: self.rmap.clone(),
config: self.config.clone(),
pool: HttpRequestPool::create(),
}
.and_then(self.endpoint.take().unwrap()),
))
}))
} else {
Ok(Async::NotReady)
}
@@ -206,27 +177,27 @@ where
}
/// Service to convert `Request` to a `ServiceRequest<S>`
pub struct AppInitService<C, P>
pub struct AppInitService<T: Service, B>
where
C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = Error>,
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
chain: C,
service: T,
rmap: Rc<ResourceMap>,
config: AppConfig,
pool: &'static HttpRequestPool,
}
impl<C, P> Service for AppInitService<C, P>
impl<T, B> Service for AppInitService<T, B>
where
C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = Error>,
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
type Request = Request;
type Response = ServiceRequest<P>;
type Error = C::Error;
type Future = C::Future;
type Response = ServiceResponse<B>;
type Error = T::Error;
type Future = T::Future;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.chain.poll_ready()
self.service.poll_ready()
}
fn call(&mut self, req: Request) -> Self::Future {
@@ -247,22 +218,22 @@ where
self.pool,
)
};
self.chain.call(ServiceRequest::from_parts(req, payload))
self.service.call(ServiceRequest::from_parts(req, payload))
}
}
pub struct AppRoutingFactory<P> {
services: Rc<Vec<(ResourceDef, HttpNewService<P>, RefCell<Option<Guards>>)>>,
default: Rc<HttpNewService<P>>,
pub struct AppRoutingFactory {
services: Rc<Vec<(ResourceDef, HttpNewService, RefCell<Option<Guards>>)>>,
default: Rc<HttpNewService>,
}
impl<P: 'static> NewService for AppRoutingFactory<P> {
type Request = ServiceRequest<P>;
impl NewService for AppRoutingFactory {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = AppRouting<P>;
type Future = AppRoutingFactoryResponse<P>;
type Service = AppRouting;
type Future = AppRoutingFactoryResponse;
fn new_service(&self, _: &()) -> Self::Future {
AppRoutingFactoryResponse {
@@ -283,23 +254,23 @@ impl<P: 'static> NewService for AppRoutingFactory<P> {
}
}
type HttpServiceFut<P> = Box<Future<Item = HttpService<P>, Error = ()>>;
type HttpServiceFut = Box<Future<Item = HttpService, Error = ()>>;
/// Create app service
#[doc(hidden)]
pub struct AppRoutingFactoryResponse<P> {
fut: Vec<CreateAppRoutingItem<P>>,
default: Option<HttpService<P>>,
default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
pub struct AppRoutingFactoryResponse {
fut: Vec<CreateAppRoutingItem>,
default: Option<HttpService>,
default_fut: Option<Box<Future<Item = HttpService, Error = ()>>>,
}
enum CreateAppRoutingItem<P> {
Future(Option<ResourceDef>, Option<Guards>, HttpServiceFut<P>),
Service(ResourceDef, Option<Guards>, HttpService<P>),
enum CreateAppRoutingItem {
Future(Option<ResourceDef>, Option<Guards>, HttpServiceFut),
Service(ResourceDef, Option<Guards>, HttpService),
}
impl<P> Future for AppRoutingFactoryResponse<P> {
type Item = AppRouting<P>;
impl Future for AppRoutingFactoryResponse {
type Item = AppRouting;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -360,14 +331,14 @@ impl<P> Future for AppRoutingFactoryResponse<P> {
}
}
pub struct AppRouting<P> {
router: Router<HttpService<P>, Guards>,
ready: Option<(ServiceRequest<P>, ResourceInfo)>,
default: Option<HttpService<P>>,
pub struct AppRouting {
router: Router<HttpService, Guards>,
ready: Option<(ServiceRequest, ResourceInfo)>,
default: Option<HttpService>,
}
impl<P> Service for AppRouting<P> {
type Request = ServiceRequest<P>;
impl Service for AppRouting {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = BoxedResponse;
@@ -380,7 +351,7 @@ impl<P> Service for AppRouting<P> {
}
}
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let res = self.router.recognize_mut_checked(&mut req, |req, guards| {
if let Some(ref guards) = guards {
for f in guards {
@@ -404,58 +375,25 @@ impl<P> Service for AppRouting<P> {
}
/// Wrapper service for routing
pub struct AppEntry<P> {
factory: Rc<RefCell<Option<AppRoutingFactory<P>>>>,
pub struct AppEntry {
factory: Rc<RefCell<Option<AppRoutingFactory>>>,
}
impl<P> AppEntry<P> {
pub fn new(factory: Rc<RefCell<Option<AppRoutingFactory<P>>>>) -> Self {
impl AppEntry {
pub fn new(factory: Rc<RefCell<Option<AppRoutingFactory>>>) -> Self {
AppEntry { factory }
}
}
impl<P: 'static> NewService for AppEntry<P> {
type Request = ServiceRequest<P>;
impl NewService for AppEntry {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = AppRouting<P>;
type Future = AppRoutingFactoryResponse<P>;
type Service = AppRouting;
type Future = AppRoutingFactoryResponse;
fn new_service(&self, _: &()) -> Self::Future {
self.factory.borrow_mut().as_mut().unwrap().new_service(&())
}
}
#[doc(hidden)]
pub struct AppChain;
impl NewService for AppChain {
type Request = ServiceRequest;
type Response = ServiceRequest;
type Error = Error;
type InitError = ();
type Service = AppChain;
type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future {
ok(AppChain)
}
}
impl Service for AppChain {
type Request = ServiceRequest;
type Response = ServiceRequest;
type Error = Error;
type Future = FutureResult<Self::Response, Self::Error>;
#[inline]
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
#[inline]
fn call(&mut self, req: ServiceRequest) -> Self::Future {
ok(req)
}
}

View File

@@ -19,25 +19,25 @@ use crate::service::{
};
type Guards = Vec<Box<Guard>>;
type HttpNewService<P> =
boxed::BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpNewService =
boxed::BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
/// Application configuration
pub struct ServiceConfig<P> {
pub struct ServiceConfig {
config: AppConfig,
root: bool,
default: Rc<HttpNewService<P>>,
default: Rc<HttpNewService>,
services: Vec<(
ResourceDef,
HttpNewService<P>,
HttpNewService,
Option<Guards>,
Option<Rc<ResourceMap>>,
)>,
}
impl<P: 'static> ServiceConfig<P> {
impl ServiceConfig {
/// Crate server settings instance
pub(crate) fn new(config: AppConfig, default: Rc<HttpNewService<P>>) -> Self {
pub(crate) fn new(config: AppConfig, default: Rc<HttpNewService>) -> Self {
ServiceConfig {
config,
default,
@@ -55,7 +55,7 @@ impl<P: 'static> ServiceConfig<P> {
self,
) -> Vec<(
ResourceDef,
HttpNewService<P>,
HttpNewService,
Option<Guards>,
Option<Rc<ResourceMap>>,
)> {
@@ -77,7 +77,7 @@ impl<P: 'static> ServiceConfig<P> {
}
/// Default resource
pub fn default_service(&self) -> Rc<HttpNewService<P>> {
pub fn default_service(&self) -> Rc<HttpNewService> {
self.default.clone()
}
@@ -90,7 +90,7 @@ impl<P: 'static> ServiceConfig<P> {
) where
F: IntoNewService<S>,
S: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -169,13 +169,13 @@ impl Default for AppConfigInner {
/// Part of application configuration could be offloaded
/// to set of external methods. This could help with
/// modularization of big application configuration.
pub struct RouterConfig<P: 'static> {
pub(crate) services: Vec<Box<ServiceFactory<P>>>,
pub struct RouterConfig {
pub(crate) services: Vec<Box<ServiceFactory>>,
pub(crate) data: Vec<Box<DataFactory>>,
pub(crate) external: Vec<ResourceDef>,
}
impl<P: 'static> RouterConfig<P> {
impl RouterConfig {
pub(crate) fn new() -> Self {
Self {
services: Vec::new(),
@@ -211,7 +211,7 @@ impl<P: 'static> RouterConfig<P> {
/// Configure route for a specific path.
///
/// This is same as `App::route()` method.
pub fn route(&mut self, path: &str, mut route: Route<P>) -> &mut Self {
pub fn route(&mut self, path: &str, mut route: Route) -> &mut Self {
self.service(
Resource::new(path)
.add_guards(route.take_guards())
@@ -224,7 +224,7 @@ impl<P: 'static> RouterConfig<P> {
/// This is same as `App::service()` method.
pub fn service<F>(&mut self, factory: F) -> &mut Self
where
F: HttpServiceFactory<P> + 'static,
F: HttpServiceFactory + 'static,
{
self.services
.push(Box::new(ServiceFactoryWrapper::new(factory)));
@@ -261,7 +261,7 @@ mod tests {
#[test]
fn test_data() {
let cfg = |cfg: &mut RouterConfig<_>| {
let cfg = |cfg: &mut RouterConfig| {
cfg.data(10usize);
};
@@ -276,7 +276,7 @@ mod tests {
#[test]
fn test_data_factory() {
let cfg = |cfg: &mut RouterConfig<_>| {
let cfg = |cfg: &mut RouterConfig| {
cfg.data_factory(|| Ok::<_, ()>(10usize));
};
@@ -288,7 +288,7 @@ mod tests {
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let cfg2 = |cfg: &mut RouterConfig<_>| {
let cfg2 = |cfg: &mut RouterConfig| {
cfg.data_factory(|| Ok::<_, ()>(10u32));
};
let mut srv = init_service(

View File

@@ -88,12 +88,13 @@ impl<T> Clone for Data<T> {
}
}
impl<T: 'static, P> FromRequest<P> for Data<T> {
impl<T: 'static> FromRequest for Data<T> {
type Config = ();
type Error = Error;
type Future = Result<Self, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
if let Some(st) = req.app_config().extensions().get::<Data<T>>() {
Ok(st.clone())
} else {
@@ -232,12 +233,13 @@ impl<T> Clone for RouteData<T> {
}
}
impl<T: 'static, P> FromRequest<P> for RouteData<T> {
impl<T: 'static> FromRequest for RouteData<T> {
type Config = ();
type Error = Error;
type Future = Result<Self, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
if let Some(st) = req.route_data::<T>() {
Ok(st.clone())
} else {

View File

@@ -10,15 +10,18 @@ use crate::request::HttpRequest;
/// Trait implemented by types that can be extracted from request.
///
/// Types that implement this trait can be used with `Route` handlers.
pub trait FromRequest<P>: Sized {
pub trait FromRequest: Sized {
/// The associated error which can be returned.
type Error: Into<Error>;
/// Future that resolves to a Self
type Future: IntoFuture<Item = Self, Error = Self::Error>;
/// Configuration for this extractor
type Config: Default + 'static;
/// Convert request to a Self
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future;
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future;
/// Convert request to a Self
///
@@ -26,6 +29,14 @@ pub trait FromRequest<P>: Sized {
fn extract(req: &HttpRequest) -> Self::Future {
Self::from_request(req, &mut Payload::None)
}
/// Create and configure config instance.
fn configure<F>(f: F) -> Self::Config
where
F: FnOnce(Self::Config) -> Self::Config,
{
f(Self::Config::default())
}
}
/// Optionally extract a field from the request
@@ -45,11 +56,12 @@ pub trait FromRequest<P>: Sized {
/// name: String
/// }
///
/// impl<P> FromRequest<P> for Thing {
/// impl FromRequest for Thing {
/// type Error = Error;
/// type Future = Result<Self, Self::Error>;
/// type Config = ();
///
/// fn from_request(req: &HttpRequest, payload: &mut dev::Payload<P>) -> Self::Future {
/// fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
/// if rand::random() {
/// Ok(Thing { name: "thingy".into() })
/// } else {
@@ -75,16 +87,17 @@ pub trait FromRequest<P>: Sized {
/// );
/// }
/// ```
impl<T: 'static, P> FromRequest<P> for Option<T>
impl<T: 'static> FromRequest for Option<T>
where
T: FromRequest<P>,
T: FromRequest,
T::Future: 'static,
{
type Config = T::Config;
type Error = Error;
type Future = Box<Future<Item = Option<T>, Error = Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
Box::new(
T::from_request(req, payload)
.into_future()
@@ -116,11 +129,12 @@ where
/// name: String
/// }
///
/// impl<P> FromRequest<P> for Thing {
/// impl FromRequest for Thing {
/// type Error = Error;
/// type Future = Result<Thing, Error>;
/// type Config = ();
///
/// fn from_request(req: &HttpRequest, payload: &mut dev::Payload<P>) -> Self::Future {
/// fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
/// if rand::random() {
/// Ok(Thing { name: "thingy".into() })
/// } else {
@@ -143,17 +157,18 @@ where
/// );
/// }
/// ```
impl<T: 'static, P> FromRequest<P> for Result<T, T::Error>
impl<T: 'static> FromRequest for Result<T, T::Error>
where
T: FromRequest<P>,
T: FromRequest,
T::Future: 'static,
T::Error: 'static,
{
type Config = T::Config;
type Error = Error;
type Future = Box<Future<Item = Result<T, T::Error>, Error = Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
Box::new(
T::from_request(req, payload)
.into_future()
@@ -166,11 +181,12 @@ where
}
#[doc(hidden)]
impl<P> FromRequest<P> for () {
impl FromRequest for () {
type Config = ();
type Error = Error;
type Future = Result<(), Error>;
fn from_request(_: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(_: &HttpRequest, _: &mut Payload) -> Self::Future {
Ok(())
}
}
@@ -179,12 +195,13 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
/// FromRequest implementation for tuple
#[doc(hidden)]
impl<P, $($T: FromRequest<P> + 'static),+> FromRequest<P> for ($($T,)+)
impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+)
{
type Error = Error;
type Future = $fut_type<P, $($T),+>;
type Future = $fut_type<$($T),+>;
type Config = ($($T::Config),+);
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
$fut_type {
items: <($(Option<$T>,)+)>::default(),
futs: ($($T::from_request(req, payload).into_future(),)+),
@@ -193,12 +210,12 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
}
#[doc(hidden)]
pub struct $fut_type<P, $($T: FromRequest<P>),+> {
pub struct $fut_type<$($T: FromRequest),+> {
items: ($(Option<$T>,)+),
futs: ($(<$T::Future as futures::IntoFuture>::Future,)+),
}
impl<P, $($T: FromRequest<P>),+> Future for $fut_type<P, $($T),+>
impl<$($T: FromRequest),+> Future for $fut_type<$($T),+>
{
type Item = ($($T,)+);
type Error = Error;

View File

@@ -242,13 +242,13 @@ where
}
/// Extract arguments from request
pub struct Extract<P, T: FromRequest<P>, S> {
pub struct Extract<T: FromRequest, S> {
config: Rc<RefCell<Option<Rc<Extensions>>>>,
service: S,
_t: PhantomData<(P, T)>,
_t: PhantomData<T>,
}
impl<P, T: FromRequest<P>, S> Extract<P, T, S> {
impl<T: FromRequest, S> Extract<T, S> {
pub fn new(config: Rc<RefCell<Option<Rc<Extensions>>>>, service: S) -> Self {
Extract {
config,
@@ -258,16 +258,16 @@ impl<P, T: FromRequest<P>, S> Extract<P, T, S> {
}
}
impl<P, T: FromRequest<P>, S> NewService for Extract<P, T, S>
impl<T: FromRequest, S> NewService for Extract<T, S>
where
S: Service<Request = (T, HttpRequest), Response = ServiceResponse, Error = Void>
+ Clone,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = (Error, ServiceRequest<P>);
type Error = (Error, ServiceRequest);
type InitError = ();
type Service = ExtractService<P, T, S>;
type Service = ExtractService<T, S>;
type Future = FutureResult<Self::Service, ()>;
fn new_service(&self, _: &()) -> Self::Future {
@@ -279,27 +279,27 @@ where
}
}
pub struct ExtractService<P, T: FromRequest<P>, S> {
pub struct ExtractService<T: FromRequest, S> {
config: Option<Rc<Extensions>>,
service: S,
_t: PhantomData<(P, T)>,
_t: PhantomData<T>,
}
impl<P, T: FromRequest<P>, S> Service for ExtractService<P, T, S>
impl<T: FromRequest, S> Service for ExtractService<T, S>
where
S: Service<Request = (T, HttpRequest), Response = ServiceResponse, Error = Void>
+ Clone,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = (Error, ServiceRequest<P>);
type Future = ExtractResponse<P, T, S>;
type Error = (Error, ServiceRequest);
type Future = ExtractResponse<T, S>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let (mut req, mut payload) = req.into_parts();
req.set_route_data(self.config.clone());
let fut = T::from_request(&req, &mut payload).into_future();
@@ -313,19 +313,19 @@ where
}
}
pub struct ExtractResponse<P, T: FromRequest<P>, S: Service> {
req: Option<(HttpRequest, Payload<P>)>,
pub struct ExtractResponse<T: FromRequest, S: Service> {
req: Option<(HttpRequest, Payload)>,
service: S,
fut: <T::Future as IntoFuture>::Future,
fut_s: Option<S::Future>,
}
impl<P, T: FromRequest<P>, S> Future for ExtractResponse<P, T, S>
impl<T: FromRequest, S> Future for ExtractResponse<T, S>
where
S: Service<Request = (T, HttpRequest), Response = ServiceResponse, Error = Void>,
{
type Item = ServiceResponse;
type Error = (Error, ServiceRequest<P>);
type Error = (Error, ServiceRequest);
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut_s {

View File

@@ -133,7 +133,6 @@ pub mod dev {
//! use actix_web::dev::*;
//! ```
pub use crate::app::AppRouter;
pub use crate::config::{AppConfig, ServiceConfig};
pub use crate::info::ConnectionInfo;
pub use crate::rmap::ResourceMap;
@@ -143,6 +142,7 @@ pub mod dev {
pub use crate::types::readlines::Readlines;
pub use actix_http::body::{Body, BodySize, MessageBody, ResponseBody};
pub use actix_http::encoding::Decoder as Decompress;
pub use actix_http::ResponseBuilder as HttpResponseBuilder;
pub use actix_http::{
Extensions, Payload, PayloadStream, RequestHead, ResponseHead,

View File

@@ -41,11 +41,11 @@ impl<B> BodyEncoding for Response<B> {
/// To disable compression set encoding to `ContentEncoding::Identity` value.
///
/// ```rust
/// use actix_web::{web, middleware::encoding, App, HttpResponse};
/// use actix_web::{web, middleware, App, HttpResponse};
///
/// fn main() {
/// let app = App::new()
/// .wrap(encoding::Compress::default())
/// .wrap(middleware::Compress::default())
/// .service(
/// web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
@@ -68,12 +68,12 @@ impl Default for Compress {
}
}
impl<S, P, B> Transform<S> for Compress
impl<S, B> Transform<S> for Compress
where
B: MessageBody,
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>;
type Error = S::Error;
type InitError = ();
@@ -93,21 +93,21 @@ pub struct CompressMiddleware<S> {
encoding: ContentEncoding,
}
impl<S, P, B> Service for CompressMiddleware<S>
impl<S, B> Service for CompressMiddleware<S>
where
B: MessageBody,
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>;
type Error = S::Error;
type Future = CompressResponse<S, P, B>;
type Future = CompressResponse<S, B>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
// negotiate content-encoding
let encoding = if let Some(val) = req.headers().get(&ACCEPT_ENCODING) {
if let Ok(enc) = val.to_str() {
@@ -128,20 +128,20 @@ where
}
#[doc(hidden)]
pub struct CompressResponse<S, P, B>
pub struct CompressResponse<S, B>
where
S: Service,
B: MessageBody,
{
fut: S::Future,
encoding: ContentEncoding,
_t: PhantomData<(P, B)>,
_t: PhantomData<(B)>,
}
impl<S, P, B> Future for CompressResponse<S, P, B>
impl<S, B> Future for CompressResponse<S, B>
where
B: MessageBody,
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
{
type Item = ServiceResponse<Encoder<B>>;
type Error = S::Error;

View File

@@ -475,9 +475,9 @@ fn cors<'a>(
parts.as_mut()
}
impl<S, P, B> IntoTransform<CorsFactory, S> for Cors
impl<S, B> IntoTransform<CorsFactory, S> for Cors
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
@@ -537,14 +537,14 @@ pub struct CorsFactory {
inner: Rc<Inner>,
}
impl<S, P, B> Transform<S> for CorsFactory
impl<S, B> Transform<S> for CorsFactory
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type InitError = ();
@@ -678,14 +678,14 @@ impl Inner {
}
}
impl<S, P, B> Service for CorsMiddleware<S>
impl<S, B> Service for CorsMiddleware<S>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type Future = Either<
@@ -697,7 +697,7 @@ where
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
if self.inner.preflight && Method::OPTIONS == *req.method() {
if let Err(e) = self
.inner
@@ -815,13 +815,12 @@ mod tests {
use actix_service::{FnService, Transform};
use super::*;
use crate::dev::PayloadStream;
use crate::test::{self, block_on, TestRequest};
impl Cors {
fn finish<S, P, B>(self, srv: S) -> CorsMiddleware<S>
fn finish<S, B>(self, srv: S) -> CorsMiddleware<S>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>
+ 'static,
S::Future: 'static,
S::Error: 'static,
@@ -1057,7 +1056,7 @@ mod tests {
.allowed_headers(exposed_headers.clone())
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish(FnService::new(move |req: ServiceRequest<PayloadStream>| {
.finish(FnService::new(move |req: ServiceRequest| {
req.into_response(
HttpResponse::Ok().header(header::VARY, "Accept").finish(),
)

View File

@@ -1,75 +0,0 @@
//! Chain service for decompressing request payload.
use std::marker::PhantomData;
use actix_http::encoding::Decoder;
use actix_service::{NewService, Service};
use bytes::Bytes;
use futures::future::{ok, FutureResult};
use futures::{Async, Poll, Stream};
use crate::dev::Payload;
use crate::error::{Error, PayloadError};
use crate::service::ServiceRequest;
/// `Middleware` for decompressing request's payload.
/// `Decompress` middleware must be added with `App::chain()` method.
///
/// ```rust
/// use actix_web::{web, middleware::encoding, App, HttpResponse};
///
/// fn main() {
/// let app = App::new()
/// .chain(encoding::Decompress::new())
/// .service(
/// web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
/// );
/// }
/// ```
pub struct Decompress<P>(PhantomData<P>);
impl<P> Decompress<P>
where
P: Stream<Item = Bytes, Error = PayloadError>,
{
pub fn new() -> Self {
Decompress(PhantomData)
}
}
impl<P> NewService for Decompress<P>
where
P: Stream<Item = Bytes, Error = PayloadError>,
{
type Request = ServiceRequest<P>;
type Response = ServiceRequest<Decoder<Payload<P>>>;
type Error = Error;
type InitError = ();
type Service = Decompress<P>;
type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future {
ok(Decompress(PhantomData))
}
}
impl<P> Service for Decompress<P>
where
P: Stream<Item = Bytes, Error = PayloadError>,
{
type Request = ServiceRequest<P>;
type Response = ServiceRequest<Decoder<Payload<P>>>;
type Error = Error;
type Future = FutureResult<Self::Response, Self::Error>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
let (req, payload) = req.into_parts();
let payload = Decoder::from_headers(payload, req.headers());
ok(ServiceRequest::from_parts(req, Payload::Stream(payload)))
}
}

View File

@@ -85,12 +85,12 @@ impl DefaultHeaders {
}
}
impl<S, P, B> Transform<S> for DefaultHeaders
impl<S, B> Transform<S> for DefaultHeaders
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type InitError = ();
@@ -110,12 +110,12 @@ pub struct DefaultHeadersMiddleware<S> {
inner: Rc<Inner>,
}
impl<S, P, B> Service for DefaultHeadersMiddleware<S>
impl<S, B> Service for DefaultHeadersMiddleware<S>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
S::Future: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
@@ -124,7 +124,7 @@ where
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let inner = self.inner.clone();
Box::new(self.service.call(req).map(move |mut res| {
@@ -171,7 +171,7 @@ mod tests {
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
let req = TestRequest::default().to_srv_request();
let srv = FnService::new(|req: ServiceRequest<_>| {
let srv = FnService::new(|req: ServiceRequest| {
req.into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish())
});
let mut mw = block_on(
@@ -186,7 +186,7 @@ mod tests {
#[test]
fn test_content_type() {
let srv = FnService::new(|req: ServiceRequest<_>| {
let srv = FnService::new(|req: ServiceRequest| {
req.into_response(HttpResponse::Ok().finish())
});
let mut mw =

View File

@@ -81,18 +81,14 @@ impl<B> ErrorHandlers<B> {
}
}
impl<S, P, B> Transform<S> for ErrorHandlers<B>
impl<S, B> Transform<S> for ErrorHandlers<B>
where
S: Service<
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = Error,
>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
@@ -113,18 +109,14 @@ pub struct ErrorHandlersMiddleware<S, B> {
handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}
impl<S, P, B> Service for ErrorHandlersMiddleware<S, B>
impl<S, B> Service for ErrorHandlersMiddleware<S, B>
where
S: Service<
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = Error,
>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
@@ -133,7 +125,7 @@ where
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let handlers = self.handlers.clone();
Box::new(self.service.call(req).and_then(move |res| {
@@ -169,7 +161,7 @@ mod tests {
#[test]
fn test_handler() {
let srv = FnService::new(|req: ServiceRequest<_>| {
let srv = FnService::new(|req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
});
@@ -195,7 +187,7 @@ mod tests {
#[test]
fn test_handler_async() {
let srv = FnService::new(|req: ServiceRequest<_>| {
let srv = FnService::new(|req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
});

View File

@@ -140,12 +140,13 @@ struct IdentityItem {
/// }
/// # fn main() {}
/// ```
impl<P> FromRequest<P> for Identity {
impl FromRequest for Identity {
type Config = ();
type Error = Error;
type Future = Result<Identity, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
Ok(Identity(req.clone()))
}
}
@@ -159,7 +160,7 @@ pub trait IdentityPolicy: Sized + 'static {
type ResponseFuture: IntoFuture<Item = (), Error = Error>;
/// Parse the session from request and load data from a service identity.
fn from_request<P>(&self, request: &mut ServiceRequest<P>) -> Self::Future;
fn from_request(&self, request: &mut ServiceRequest) -> Self::Future;
/// Write changes to response
fn to_response<B>(
@@ -198,16 +199,15 @@ impl<T> IdentityService<T> {
}
}
impl<S, T, P, B> Transform<S> for IdentityService<T>
impl<S, T, B> Transform<S> for IdentityService<T>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>> + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>> + 'static,
S::Future: 'static,
S::Error: 'static,
T: IdentityPolicy,
P: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type InitError = ();
@@ -228,16 +228,15 @@ pub struct IdentityServiceMiddleware<S, T> {
service: Rc<RefCell<S>>,
}
impl<S, T, P, B> Service for IdentityServiceMiddleware<S, T>
impl<S, T, B> Service for IdentityServiceMiddleware<S, T>
where
P: 'static,
B: 'static,
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>> + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>> + 'static,
S::Future: 'static,
S::Error: 'static,
T: IdentityPolicy,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = S::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
@@ -246,7 +245,7 @@ where
self.service.borrow_mut().poll_ready()
}
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let srv = self.service.clone();
let backend = self.backend.clone();
@@ -348,7 +347,7 @@ impl CookieIdentityInner {
Ok(())
}
fn load<T>(&self, req: &ServiceRequest<T>) -> Option<String> {
fn load(&self, req: &ServiceRequest) -> Option<String> {
if let Ok(cookies) = req.cookies() {
for cookie in cookies.iter() {
if cookie.name() == self.name {
@@ -445,7 +444,7 @@ impl IdentityPolicy for CookieIdentityPolicy {
type Future = Result<Option<String>, Error>;
type ResponseFuture = Result<(), Error>;
fn from_request<P>(&self, req: &mut ServiceRequest<P>) -> Self::Future {
fn from_request(&self, req: &mut ServiceRequest) -> Self::Future {
Ok(self.0.load(req))
}

View File

@@ -114,12 +114,12 @@ impl Default for Logger {
}
}
impl<S, P, B> Transform<S> for Logger
impl<S, B> Transform<S> for Logger
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
B: MessageBody,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>;
type Error = S::Error;
type InitError = ();
@@ -140,21 +140,21 @@ pub struct LoggerMiddleware<S> {
service: S,
}
impl<S, P, B> Service for LoggerMiddleware<S>
impl<S, B> Service for LoggerMiddleware<S>
where
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
B: MessageBody,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>;
type Error = S::Error;
type Future = LoggerResponse<S, P, B>;
type Future = LoggerResponse<S, B>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
if self.inner.exclude.contains(req.path()) {
LoggerResponse {
fut: self.service.call(req),
@@ -180,7 +180,7 @@ where
}
#[doc(hidden)]
pub struct LoggerResponse<S, P, B>
pub struct LoggerResponse<S, B>
where
B: MessageBody,
S: Service,
@@ -188,13 +188,13 @@ where
fut: S::Future,
time: time::Tm,
format: Option<Format>,
_t: PhantomData<(P, B)>,
_t: PhantomData<(B,)>,
}
impl<S, P, B> Future for LoggerResponse<S, P, B>
impl<S, B> Future for LoggerResponse<S, B>
where
B: MessageBody,
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>>,
{
type Item = ServiceResponse<StreamLog<B>>;
type Error = S::Error;
@@ -402,7 +402,7 @@ impl FormatText {
}
}
fn render_request<P>(&mut self, now: time::Tm, req: &ServiceRequest<P>) {
fn render_request(&mut self, now: time::Tm, req: &ServiceRequest) {
match *self {
FormatText::RequestLine => {
*self = if req.query_string().is_empty() {
@@ -464,7 +464,7 @@ mod tests {
#[test]
fn test_logger() {
let srv = FnService::new(|req: ServiceRequest<_>| {
let srv = FnService::new(|req: ServiceRequest| {
req.into_response(
HttpResponse::build(StatusCode::OK)
.header("X-Test", "ttt")

View File

@@ -1,14 +1,6 @@
//! Middlewares
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
mod compress;
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
mod decompress;
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
pub mod encoding {
//! Middlewares for compressing/decompressing payloads.
pub use super::compress::{BodyEncoding, Compress};
pub use super::decompress::Decompress;
}
pub use self::compress::{BodyEncoding, Compress};
pub mod cors;
mod defaultheaders;

View File

@@ -265,12 +265,13 @@ impl Drop for HttpRequest {
/// );
/// }
/// ```
impl<P> FromRequest<P> for HttpRequest {
impl FromRequest for HttpRequest {
type Config = ();
type Error = Error;
type Future = Result<Self, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
Ok(req.clone())
}
}

View File

@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use actix_http::{Error, Response};
@@ -17,9 +18,8 @@ use crate::responder::Responder;
use crate::route::{CreateRouteService, Route, RouteService};
use crate::service::{ServiceRequest, ServiceResponse};
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
/// *Resource* is an entry in resources table which corresponds to requested URL.
///
@@ -43,18 +43,18 @@ type HttpNewService<P> =
///
/// If no matching route could be found, *405* response code get returned.
/// Default behavior could be overriden with `default_resource()` method.
pub struct Resource<P, T = ResourceEndpoint<P>> {
pub struct Resource<T = ResourceEndpoint> {
endpoint: T,
rdef: String,
name: Option<String>,
routes: Vec<Route<P>>,
routes: Vec<Route>,
guards: Vec<Box<Guard>>,
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
factory_ref: Rc<RefCell<Option<ResourceFactory>>>,
}
impl<P> Resource<P> {
pub fn new(path: &str) -> Resource<P> {
impl Resource {
pub fn new(path: &str) -> Resource {
let fref = Rc::new(RefCell::new(None));
Resource {
@@ -69,11 +69,10 @@ impl<P> Resource<P> {
}
}
impl<P, T> Resource<P, T>
impl<T> Resource<T>
where
P: 'static,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -154,7 +153,7 @@ where
/// # fn post_handler() {}
/// # fn delete_handler() {}
/// ```
pub fn route(mut self, route: Route<P>) -> Self {
pub fn route(mut self, route: Route) -> Self {
self.routes.push(route.finish());
self
}
@@ -182,7 +181,7 @@ where
pub fn to<F, I, R>(mut self, handler: F) -> Self
where
F: Factory<I, R> + 'static,
I: FromRequest<P> + 'static,
I: FromRequest + 'static,
R: Responder + 'static,
{
self.routes.push(Route::new().to(handler));
@@ -216,7 +215,7 @@ where
pub fn to_async<F, I, R>(mut self, handler: F) -> Self
where
F: AsyncFactory<I, R>,
I: FromRequest<P> + 'static,
I: FromRequest + 'static,
R: IntoFuture + 'static,
R::Item: Into<Response>,
R::Error: Into<Error>,
@@ -236,9 +235,8 @@ where
self,
mw: F,
) -> Resource<
P,
impl NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -247,7 +245,7 @@ where
where
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -302,54 +300,54 @@ where
self,
mw: F,
) -> Resource<
P,
impl NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
>,
>
where
F: FnMut(ServiceRequest<P>, &mut T::Service) -> R + Clone,
F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone,
R: IntoFuture<Item = ServiceResponse, Error = Error>,
{
self.wrap(mw)
}
/// Default resource to be used if no matching route could be found.
/// Default service to be used if no matching route could be found.
/// By default *405* response get returned. Resource does not use
/// default handler from `App` or `Scope`.
pub fn default_resource<F, R, U>(mut self, f: F) -> Self
pub fn default_service<F, U>(mut self, f: F) -> Self
where
F: FnOnce(Resource<P>) -> R,
R: IntoNewService<U>,
F: IntoNewService<U>,
U: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
> + 'static,
U::InitError: fmt::Debug,
{
// create and configure default resource
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
f(Resource::new("")).into_new_service().map_init_err(|_| ()),
f.into_new_service().map_init_err(|e| {
log::error!("Can not construct default service: {:?}", e)
}),
)))));
self
}
}
impl<P, T> HttpServiceFactory<P> for Resource<P, T>
impl<T> HttpServiceFactory for Resource<T>
where
P: 'static,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
> + 'static,
{
fn register(mut self, config: &mut ServiceConfig<P>) {
fn register(mut self, config: &mut ServiceConfig) {
let guards = if self.guards.is_empty() {
None
} else {
@@ -367,10 +365,10 @@ where
}
}
impl<P, T> IntoNewService<T> for Resource<P, T>
impl<T> IntoNewService<T> for Resource<T>
where
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -386,18 +384,18 @@ where
}
}
pub struct ResourceFactory<P> {
routes: Vec<Route<P>>,
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
pub struct ResourceFactory {
routes: Vec<Route>,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
}
impl<P: 'static> NewService for ResourceFactory<P> {
type Request = ServiceRequest<P>;
impl NewService for ResourceFactory {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = ResourceService<P>;
type Future = CreateResourceService<P>;
type Service = ResourceService;
type Future = CreateResourceService;
fn new_service(&self, _: &()) -> Self::Future {
let default_fut = if let Some(ref default) = *self.default.borrow() {
@@ -418,19 +416,19 @@ impl<P: 'static> NewService for ResourceFactory<P> {
}
}
enum CreateRouteServiceItem<P> {
Future(CreateRouteService<P>),
Service(RouteService<P>),
enum CreateRouteServiceItem {
Future(CreateRouteService),
Service(RouteService),
}
pub struct CreateResourceService<P> {
fut: Vec<CreateRouteServiceItem<P>>,
default: Option<HttpService<P>>,
default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
pub struct CreateResourceService {
fut: Vec<CreateRouteServiceItem>,
default: Option<HttpService>,
default_fut: Option<Box<Future<Item = HttpService, Error = ()>>>,
}
impl<P> Future for CreateResourceService<P> {
type Item = ResourceService<P>;
impl Future for CreateResourceService {
type Item = ResourceService;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -477,13 +475,13 @@ impl<P> Future for CreateResourceService<P> {
}
}
pub struct ResourceService<P> {
routes: Vec<RouteService<P>>,
default: Option<HttpService<P>>,
pub struct ResourceService {
routes: Vec<RouteService>,
default: Option<HttpService>,
}
impl<P> Service for ResourceService<P> {
type Request = ServiceRequest<P>;
impl Service for ResourceService {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = Either<
@@ -495,7 +493,7 @@ impl<P> Service for ResourceService<P> {
Ok(Async::Ready(()))
}
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
for route in self.routes.iter_mut() {
if route.check(&mut req) {
return route.call(req);
@@ -514,23 +512,23 @@ impl<P> Service for ResourceService<P> {
}
#[doc(hidden)]
pub struct ResourceEndpoint<P> {
factory: Rc<RefCell<Option<ResourceFactory<P>>>>,
pub struct ResourceEndpoint {
factory: Rc<RefCell<Option<ResourceFactory>>>,
}
impl<P> ResourceEndpoint<P> {
fn new(factory: Rc<RefCell<Option<ResourceFactory<P>>>>) -> Self {
impl ResourceEndpoint {
fn new(factory: Rc<RefCell<Option<ResourceFactory>>>) -> Self {
ResourceEndpoint { factory }
}
}
impl<P: 'static> NewService for ResourceEndpoint<P> {
type Request = ServiceRequest<P>;
impl NewService for ResourceEndpoint {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = ResourceService<P>;
type Future = CreateResourceService<P>;
type Service = ResourceService;
type Future = CreateResourceService;
fn new_service(&self, _: &()) -> Self::Future {
self.factory.borrow_mut().as_mut().unwrap().new_service(&())
@@ -550,13 +548,13 @@ mod tests {
use crate::test::{call_success, init_service, TestRequest};
use crate::{web, App, Error, HttpResponse};
fn md<S, P, B>(
req: ServiceRequest<P>,
fn md<S, B>(
req: ServiceRequest,
srv: &mut S,
) -> impl IntoFuture<Item = ServiceResponse<B>, Error = Error>
where
S: Service<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
>,
@@ -631,7 +629,9 @@ mod tests {
.service(
web::resource("/test").route(web::get().to(|| HttpResponse::Ok())),
)
.default_resource(|r| r.to(|| HttpResponse::BadRequest())),
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::BadRequest())
}),
);
let req = TestRequest::with_uri("/test").to_request();
let resp = call_success(&mut srv, req);
@@ -647,7 +647,9 @@ mod tests {
App::new().service(
web::resource("/test")
.route(web::get().to(|| HttpResponse::Ok()))
.default_resource(|r| r.to(|| HttpResponse::BadRequest())),
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::BadRequest())
}),
),
);

View File

@@ -1,5 +1,4 @@
use std::cell::RefCell;
use std::marker::PhantomData;
use std::rc::Rc;
use actix_http::{http::Method, Error, Extensions, Response};
@@ -42,16 +41,16 @@ type BoxedRouteNewService<Req, Res> = Box<
///
/// Route uses builder-like pattern for configuration.
/// If handler is not explicitly set, default *404 Not Found* handler is used.
pub struct Route<P> {
service: BoxedRouteNewService<ServiceRequest<P>, ServiceResponse>,
pub struct Route {
service: BoxedRouteNewService<ServiceRequest, ServiceResponse>,
guards: Rc<Vec<Box<Guard>>>,
data: Option<Extensions>,
data_ref: Rc<RefCell<Option<Rc<Extensions>>>>,
}
impl<P: 'static> Route<P> {
impl Route {
/// Create new route which matches any request.
pub fn new() -> Route<P> {
pub fn new() -> Route {
let data_ref = Rc::new(RefCell::new(None));
Route {
service: Box::new(RouteNewService::new(Extract::new(
@@ -74,13 +73,13 @@ impl<P: 'static> Route<P> {
}
}
impl<P> NewService for Route<P> {
type Request = ServiceRequest<P>;
impl NewService for Route {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = RouteService<P>;
type Future = CreateRouteService<P>;
type Service = RouteService;
type Future = CreateRouteService;
fn new_service(&self, _: &()) -> Self::Future {
CreateRouteService {
@@ -90,17 +89,16 @@ impl<P> NewService for Route<P> {
}
}
type RouteFuture<P> = Box<
Future<Item = BoxedRouteService<ServiceRequest<P>, ServiceResponse>, Error = ()>,
>;
type RouteFuture =
Box<Future<Item = BoxedRouteService<ServiceRequest, ServiceResponse>, Error = ()>>;
pub struct CreateRouteService<P> {
fut: RouteFuture<P>,
pub struct CreateRouteService {
fut: RouteFuture,
guards: Rc<Vec<Box<Guard>>>,
}
impl<P> Future for CreateRouteService<P> {
type Item = RouteService<P>;
impl Future for CreateRouteService {
type Item = RouteService;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -114,13 +112,13 @@ impl<P> Future for CreateRouteService<P> {
}
}
pub struct RouteService<P> {
service: BoxedRouteService<ServiceRequest<P>, ServiceResponse>,
pub struct RouteService {
service: BoxedRouteService<ServiceRequest, ServiceResponse>,
guards: Rc<Vec<Box<Guard>>>,
}
impl<P> RouteService<P> {
pub fn check(&self, req: &mut ServiceRequest<P>) -> bool {
impl RouteService {
pub fn check(&self, req: &mut ServiceRequest) -> bool {
for f in self.guards.iter() {
if !f.check(req.head()) {
return false;
@@ -130,8 +128,8 @@ impl<P> RouteService<P> {
}
}
impl<P> Service for RouteService<P> {
type Request = ServiceRequest<P>;
impl Service for RouteService {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = Either<
@@ -143,12 +141,12 @@ impl<P> Service for RouteService<P> {
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
self.service.call(req)
}
}
impl<P: 'static> Route<P> {
impl Route {
/// Add method guard to the route.
///
/// ```rust
@@ -235,10 +233,10 @@ impl<P: 'static> Route<P> {
/// );
/// }
/// ```
pub fn to<F, T, R>(mut self, handler: F) -> Route<P>
pub fn to<F, T, R>(mut self, handler: F) -> Route
where
F: Factory<T, R> + 'static,
T: FromRequest<P> + 'static,
T: FromRequest + 'static,
R: Responder + 'static,
{
self.service = Box::new(RouteNewService::new(Extract::new(
@@ -278,7 +276,7 @@ impl<P: 'static> Route<P> {
pub fn to_async<F, T, R>(mut self, handler: F) -> Self
where
F: AsyncFactory<T, R>,
T: FromRequest<P> + 'static,
T: FromRequest + 'static,
R: IntoFuture + 'static,
R::Item: Into<Response>,
R::Error: Into<Error>,
@@ -294,7 +292,7 @@ impl<P: 'static> Route<P> {
/// configuration or specific state available via `RouteData<T>` extractor.
///
/// ```rust
/// use actix_web::{web, App};
/// use actix_web::{web, App, FromRequest};
///
/// /// extract text data from request
/// fn index(body: String) -> String {
@@ -306,13 +304,15 @@ impl<P: 'static> Route<P> {
/// web::resource("/index.html").route(
/// web::get()
/// // limit size of the payload
/// .data(web::PayloadConfig::new(4096))
/// .data(String::configure(|cfg| {
/// cfg.limit(4096)
/// }))
/// // register handler
/// .to(index)
/// ));
/// }
/// ```
pub fn data<C: 'static>(mut self, data: C) -> Self {
pub fn data<T: 'static>(mut self, data: T) -> Self {
if self.data.is_none() {
self.data = Some(Extensions::new());
}
@@ -321,49 +321,45 @@ impl<P: 'static> Route<P> {
}
}
struct RouteNewService<P, T>
struct RouteNewService<T>
where
T: NewService<Request = ServiceRequest<P>, Error = (Error, ServiceRequest<P>)>,
T: NewService<Request = ServiceRequest, Error = (Error, ServiceRequest)>,
{
service: T,
_t: PhantomData<P>,
}
impl<P: 'static, T> RouteNewService<P, T>
impl<T> RouteNewService<T>
where
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = (Error, ServiceRequest<P>),
Error = (Error, ServiceRequest),
>,
T::Future: 'static,
T::Service: 'static,
<T::Service as Service>::Future: 'static,
{
pub fn new(service: T) -> Self {
RouteNewService {
service,
_t: PhantomData,
}
RouteNewService { service }
}
}
impl<P: 'static, T> NewService for RouteNewService<P, T>
impl<T> NewService for RouteNewService<T>
where
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = (Error, ServiceRequest<P>),
Error = (Error, ServiceRequest),
>,
T::Future: 'static,
T::Service: 'static,
<T::Service as Service>::Future: 'static,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = BoxedRouteService<ServiceRequest<P>, Self::Response>;
type Service = BoxedRouteService<ServiceRequest, Self::Response>;
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
fn new_service(&self, _: &()) -> Self::Future {
@@ -373,31 +369,27 @@ where
.map_err(|_| ())
.and_then(|service| {
let service: BoxedRouteService<_, _> =
Box::new(RouteServiceWrapper {
service,
_t: PhantomData,
});
Box::new(RouteServiceWrapper { service });
Ok(service)
}),
)
}
}
struct RouteServiceWrapper<P, T: Service> {
struct RouteServiceWrapper<T: Service> {
service: T,
_t: PhantomData<P>,
}
impl<P, T> Service for RouteServiceWrapper<P, T>
impl<T> Service for RouteServiceWrapper<T>
where
T::Future: 'static,
T: Service<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = (Error, ServiceRequest<P>),
Error = (Error, ServiceRequest),
>,
{
type Request = ServiceRequest<P>;
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = Either<
@@ -409,7 +401,7 @@ where
self.service.poll_ready().map_err(|(e, _)| e)
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let mut fut = self.service.call(req);
match fut.poll() {
Ok(Async::Ready(res)) => Either::A(ok(res)),

View File

@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use actix_http::Response;
@@ -21,9 +22,8 @@ use crate::service::{
};
type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>;
type BoxedResponse = Either<
FutureResult<ServiceResponse, Error>,
Box<Future<Item = ServiceResponse, Error = Error>>,
@@ -58,18 +58,18 @@ type BoxedResponse = Either<
/// * /{project_id}/path2 - `GET` requests
/// * /{project_id}/path3 - `HEAD` requests
///
pub struct Scope<P, T = ScopeEndpoint<P>> {
pub struct Scope<T = ScopeEndpoint> {
endpoint: T,
rdef: String,
services: Vec<Box<ServiceFactory<P>>>,
services: Vec<Box<ServiceFactory>>,
guards: Vec<Box<Guard>>,
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
factory_ref: Rc<RefCell<Option<ScopeFactory<P>>>>,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
factory_ref: Rc<RefCell<Option<ScopeFactory>>>,
}
impl<P: 'static> Scope<P> {
impl Scope {
/// Create a new scope
pub fn new(path: &str) -> Scope<P> {
pub fn new(path: &str) -> Scope {
let fref = Rc::new(RefCell::new(None));
Scope {
endpoint: ScopeEndpoint::new(fref.clone()),
@@ -82,11 +82,10 @@ impl<P: 'static> Scope<P> {
}
}
impl<P, T> Scope<P, T>
impl<T> Scope<T>
where
P: 'static,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -146,7 +145,7 @@ where
/// ```
pub fn service<F>(mut self, factory: F) -> Self
where
F: HttpServiceFactory<P> + 'static,
F: HttpServiceFactory + 'static,
{
self.services
.push(Box::new(ServiceFactoryWrapper::new(factory)));
@@ -174,7 +173,7 @@ where
/// );
/// }
/// ```
pub fn route(self, path: &str, mut route: Route<P>) -> Self {
pub fn route(self, path: &str, mut route: Route) -> Self {
self.service(
Resource::new(path)
.add_guards(route.take_guards())
@@ -182,22 +181,24 @@ where
)
}
/// Default resource to be used if no matching route could be found.
/// Default service to be used if no matching route could be found.
///
/// If default resource is not registered, app's default resource is being used.
pub fn default_resource<F, U>(mut self, f: F) -> Self
pub fn default_service<F, U>(mut self, f: F) -> Self
where
F: FnOnce(Resource<P>) -> Resource<P, U>,
F: IntoNewService<U>,
U: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
> + 'static,
U::InitError: fmt::Debug,
{
// create and configure default resource
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
f(Resource::new("")).into_new_service().map_init_err(|_| ()),
f.into_new_service().map_init_err(|e| {
log::error!("Can not construct default service: {:?}", e)
}),
)))));
self
@@ -216,9 +217,8 @@ where
self,
mw: F,
) -> Scope<
P,
impl NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -227,7 +227,7 @@ where
where
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
@@ -279,33 +279,31 @@ where
self,
mw: F,
) -> Scope<
P,
impl NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
>,
>
where
F: FnMut(ServiceRequest<P>, &mut T::Service) -> R + Clone,
F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone,
R: IntoFuture<Item = ServiceResponse, Error = Error>,
{
self.wrap(mw)
}
}
impl<P, T> HttpServiceFactory<P> for Scope<P, T>
impl<T> HttpServiceFactory for Scope<T>
where
P: 'static,
T: NewService<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse,
Error = Error,
InitError = (),
> + 'static,
{
fn register(self, config: &mut ServiceConfig<P>) {
fn register(self, config: &mut ServiceConfig) {
// update default resource if needed
if self.default.borrow().is_none() {
*self.default.borrow_mut() = Some(config.default_service());
@@ -350,18 +348,18 @@ where
}
}
pub struct ScopeFactory<P> {
services: Rc<Vec<(ResourceDef, HttpNewService<P>, RefCell<Option<Guards>>)>>,
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
pub struct ScopeFactory {
services: Rc<Vec<(ResourceDef, HttpNewService, RefCell<Option<Guards>>)>>,
default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
}
impl<P: 'static> NewService for ScopeFactory<P> {
type Request = ServiceRequest<P>;
impl NewService for ScopeFactory {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>;
type Service = ScopeService;
type Future = ScopeFactoryResponse;
fn new_service(&self, _: &()) -> Self::Future {
let default_fut = if let Some(ref default) = *self.default.borrow() {
@@ -390,21 +388,21 @@ impl<P: 'static> NewService for ScopeFactory<P> {
/// Create scope service
#[doc(hidden)]
pub struct ScopeFactoryResponse<P> {
fut: Vec<CreateScopeServiceItem<P>>,
default: Option<HttpService<P>>,
default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
pub struct ScopeFactoryResponse {
fut: Vec<CreateScopeServiceItem>,
default: Option<HttpService>,
default_fut: Option<Box<Future<Item = HttpService, Error = ()>>>,
}
type HttpServiceFut<P> = Box<Future<Item = HttpService<P>, Error = ()>>;
type HttpServiceFut = Box<Future<Item = HttpService, Error = ()>>;
enum CreateScopeServiceItem<P> {
Future(Option<ResourceDef>, Option<Guards>, HttpServiceFut<P>),
Service(ResourceDef, Option<Guards>, HttpService<P>),
enum CreateScopeServiceItem {
Future(Option<ResourceDef>, Option<Guards>, HttpServiceFut),
Service(ResourceDef, Option<Guards>, HttpService),
}
impl<P> Future for ScopeFactoryResponse<P> {
type Item = ScopeService<P>;
impl Future for ScopeFactoryResponse {
type Item = ScopeService;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -465,14 +463,14 @@ impl<P> Future for ScopeFactoryResponse<P> {
}
}
pub struct ScopeService<P> {
router: Router<HttpService<P>, Vec<Box<Guard>>>,
default: Option<HttpService<P>>,
_ready: Option<(ServiceRequest<P>, ResourceInfo)>,
pub struct ScopeService {
router: Router<HttpService, Vec<Box<Guard>>>,
default: Option<HttpService>,
_ready: Option<(ServiceRequest, ResourceInfo)>,
}
impl<P> Service for ScopeService<P> {
type Request = ServiceRequest<P>;
impl Service for ScopeService {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = Either<BoxedResponse, FutureResult<Self::Response, Self::Error>>;
@@ -481,7 +479,7 @@ impl<P> Service for ScopeService<P> {
Ok(Async::Ready(()))
}
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let res = self.router.recognize_mut_checked(&mut req, |req, guards| {
if let Some(ref guards) = guards {
for f in guards {
@@ -505,23 +503,23 @@ impl<P> Service for ScopeService<P> {
}
#[doc(hidden)]
pub struct ScopeEndpoint<P> {
factory: Rc<RefCell<Option<ScopeFactory<P>>>>,
pub struct ScopeEndpoint {
factory: Rc<RefCell<Option<ScopeFactory>>>,
}
impl<P> ScopeEndpoint<P> {
fn new(factory: Rc<RefCell<Option<ScopeFactory<P>>>>) -> Self {
impl ScopeEndpoint {
fn new(factory: Rc<RefCell<Option<ScopeFactory>>>) -> Self {
ScopeEndpoint { factory }
}
}
impl<P: 'static> NewService for ScopeEndpoint<P> {
type Request = ServiceRequest<P>;
impl NewService for ScopeEndpoint {
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>;
type Service = ScopeService;
type Future = ScopeFactoryResponse;
fn new_service(&self, _: &()) -> Self::Future {
self.factory.borrow_mut().as_mut().unwrap().new_service(&())
@@ -848,7 +846,9 @@ mod tests {
App::new().service(
web::scope("/app")
.service(web::resource("/path1").to(|| HttpResponse::Ok()))
.default_resource(|r| r.to(|| HttpResponse::BadRequest())),
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::BadRequest())
}),
),
);
@@ -865,12 +865,13 @@ mod tests {
fn test_default_resource_propagation() {
let mut srv = init_service(
App::new()
.service(
web::scope("/app1")
.default_resource(|r| r.to(|| HttpResponse::BadRequest())),
)
.service(web::scope("/app1").default_service(
web::resource("").to(|| HttpResponse::BadRequest()),
))
.service(web::scope("/app2"))
.default_resource(|r| r.to(|| HttpResponse::MethodNotAllowed())),
.default_service(|r: ServiceRequest| {
r.into_response(HttpResponse::MethodNotAllowed())
}),
);
let req = TestRequest::with_uri("/non-exist").to_request();
@@ -886,13 +887,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
}
fn md<S, P, B>(
req: ServiceRequest<P>,
fn md<S, B>(
req: ServiceRequest,
srv: &mut S,
) -> impl IntoFuture<Item = ServiceResponse<B>, Error = Error>
where
S: Service<
Request = ServiceRequest<P>,
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
>,

View File

@@ -1,6 +1,5 @@
use std::cell::{Ref, RefMut};
use std::fmt;
use std::marker::PhantomData;
use actix_http::body::{Body, MessageBody, ResponseBody};
use actix_http::http::{HeaderMap, Method, StatusCode, Uri, Version};
@@ -15,59 +14,57 @@ use crate::config::{AppConfig, ServiceConfig};
use crate::data::Data;
use crate::request::HttpRequest;
pub trait HttpServiceFactory<P> {
fn register(self, config: &mut ServiceConfig<P>);
pub trait HttpServiceFactory {
fn register(self, config: &mut ServiceConfig);
}
pub(crate) trait ServiceFactory<P> {
fn register(&mut self, config: &mut ServiceConfig<P>);
pub(crate) trait ServiceFactory {
fn register(&mut self, config: &mut ServiceConfig);
}
pub(crate) struct ServiceFactoryWrapper<T, P> {
pub(crate) struct ServiceFactoryWrapper<T> {
factory: Option<T>,
_t: PhantomData<P>,
}
impl<T, P> ServiceFactoryWrapper<T, P> {
impl<T> ServiceFactoryWrapper<T> {
pub fn new(factory: T) -> Self {
Self {
factory: Some(factory),
_t: PhantomData,
}
}
}
impl<T, P> ServiceFactory<P> for ServiceFactoryWrapper<T, P>
impl<T> ServiceFactory for ServiceFactoryWrapper<T>
where
T: HttpServiceFactory<P>,
T: HttpServiceFactory,
{
fn register(&mut self, config: &mut ServiceConfig<P>) {
fn register(&mut self, config: &mut ServiceConfig) {
if let Some(item) = self.factory.take() {
item.register(config)
}
}
}
pub struct ServiceRequest<P = PayloadStream> {
pub struct ServiceRequest {
req: HttpRequest,
payload: Payload<P>,
payload: Payload,
}
impl<P> ServiceRequest<P> {
impl ServiceRequest {
/// Construct service request from parts
pub fn from_parts(req: HttpRequest, payload: Payload<P>) -> Self {
pub fn from_parts(req: HttpRequest, payload: Payload) -> Self {
ServiceRequest { req, payload }
}
/// Deconstruct request into parts
pub fn into_parts(self) -> (HttpRequest, Payload<P>) {
pub fn into_parts(self) -> (HttpRequest, Payload) {
(self.req, self.payload)
}
/// Create service response
#[inline]
pub fn into_response<B>(self, res: Response<B>) -> ServiceResponse<B> {
ServiceResponse::new(self.req, res)
pub fn into_response<B, R: Into<Response<B>>>(self, res: R) -> ServiceResponse<B> {
ServiceResponse::new(self.req, res.into())
}
/// Create service response for error
@@ -170,14 +167,14 @@ impl<P> ServiceRequest<P> {
}
}
impl<P> Resource<Url> for ServiceRequest<P> {
impl Resource<Url> for ServiceRequest {
fn resource_path(&mut self) -> &mut Path<Url> {
self.match_info_mut()
}
}
impl<P> HttpMessage for ServiceRequest<P> {
type Stream = P;
impl HttpMessage for ServiceRequest {
type Stream = PayloadStream;
#[inline]
/// Returns Request's headers.
@@ -203,7 +200,7 @@ impl<P> HttpMessage for ServiceRequest<P> {
}
}
impl<P> fmt::Debug for ServiceRequest<P> {
impl fmt::Debug for ServiceRequest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,

View File

@@ -6,7 +6,7 @@ use actix_http::cookie::Cookie;
use actix_http::http::header::{Header, HeaderName, IntoHeaderValue};
use actix_http::http::{HttpTryFrom, Method, StatusCode, Version};
use actix_http::test::TestRequest as HttpTestRequest;
use actix_http::{Extensions, PayloadStream, Request};
use actix_http::{Extensions, Request};
use actix_router::{Path, ResourceDef, Url};
use actix_rt::Runtime;
use actix_server_config::ServerConfig;
@@ -60,23 +60,18 @@ where
}
/// Create service that always responds with `HttpResponse::Ok()`
pub fn ok_service() -> impl Service<
Request = ServiceRequest<PayloadStream>,
Response = ServiceResponse<Body>,
Error = Error,
> {
pub fn ok_service(
) -> impl Service<Request = ServiceRequest, Response = ServiceResponse<Body>, Error = Error>
{
default_service(StatusCode::OK)
}
/// Create service that responds with response with specified status code
pub fn default_service(
status_code: StatusCode,
) -> impl Service<
Request = ServiceRequest<PayloadStream>,
Response = ServiceResponse<Body>,
Error = Error,
> {
FnService::new(move |req: ServiceRequest<PayloadStream>| {
) -> impl Service<Request = ServiceRequest, Response = ServiceResponse<Body>, Error = Error>
{
FnService::new(move |req: ServiceRequest| {
req.into_response(HttpResponse::build(status_code).finish())
})
}
@@ -298,12 +293,12 @@ impl TestRequest {
}
/// Complete request creation and generate `Request` instance
pub fn to_request(mut self) -> Request<PayloadStream> {
pub fn to_request(mut self) -> Request {
self.req.finish()
}
/// Complete request creation and generate `ServiceRequest` instance
pub fn to_srv_request(mut self) -> ServiceRequest<PayloadStream> {
pub fn to_srv_request(mut self) -> ServiceRequest {
let (head, payload) = self.req.finish().into_parts();
let req = HttpRequest::new(

View File

@@ -3,15 +3,15 @@
use std::rc::Rc;
use std::{fmt, ops};
use actix_http::error::{Error, PayloadError};
use actix_http::{HttpMessage, Payload};
use bytes::{Bytes, BytesMut};
use actix_http::{Error, HttpMessage, Payload};
use bytes::BytesMut;
use encoding::all::UTF_8;
use encoding::types::{DecoderTrap, Encoding};
use encoding::EncodingRef;
use futures::{Future, Poll, Stream};
use serde::de::DeserializeOwned;
use crate::dev::Decompress;
use crate::error::UrlencodedError;
use crate::extract::FromRequest;
use crate::http::header::CONTENT_LENGTH;
@@ -69,16 +69,16 @@ impl<T> ops::DerefMut for Form<T> {
}
}
impl<T, P> FromRequest<P> for Form<T>
impl<T> FromRequest for Form<T>
where
T: DeserializeOwned + 'static,
P: Stream<Item = Bytes, Error = crate::error::PayloadError> + 'static,
{
type Config = FormConfig;
type Error = Error;
type Future = Box<Future<Item = Self, Error = Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let req2 = req.clone();
let (limit, err) = req
.route_data::<FormConfig>()
@@ -116,7 +116,7 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
///
/// ```rust
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{web, App, Result};
/// use actix_web::{web, App, FromRequest, Result};
///
/// #[derive(Deserialize)]
/// struct FormData {
@@ -134,7 +134,9 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
/// web::resource("/index.html")
/// .route(web::get()
/// // change `Form` extractor configuration
/// .data(web::FormConfig::default().limit(4097))
/// .data(
/// web::Form::<FormData>::configure(|cfg| cfg.limit(4097))
/// )
/// .to(index))
/// );
/// }
@@ -182,8 +184,8 @@ impl Default for FormConfig {
/// * content type is not `application/x-www-form-urlencoded`
/// * content-length is greater than 32k
///
pub struct UrlEncoded<P, U> {
stream: Payload<P>,
pub struct UrlEncoded<U> {
stream: Option<Decompress<Payload>>,
limit: usize,
length: Option<usize>,
encoding: EncodingRef,
@@ -191,12 +193,9 @@ pub struct UrlEncoded<P, U> {
fut: Option<Box<Future<Item = U, Error = UrlencodedError>>>,
}
impl<P, U> UrlEncoded<P, U>
where
P: Stream<Item = Bytes, Error = PayloadError>,
{
impl<U> UrlEncoded<U> {
/// Create a new future to URL encode a request
pub fn new(req: &HttpRequest, payload: &mut Payload<P>) -> UrlEncoded<P, U> {
pub fn new(req: &HttpRequest, payload: &mut Payload) -> UrlEncoded<U> {
// check content type
if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" {
return Self::err(UrlencodedError::ContentType);
@@ -219,9 +218,10 @@ where
}
};
let payload = Decompress::from_headers(payload.take(), req.headers());
UrlEncoded {
encoding,
stream: payload.take(),
stream: Some(payload),
limit: 32_768,
length: len,
fut: None,
@@ -231,7 +231,7 @@ where
fn err(e: UrlencodedError) -> Self {
UrlEncoded {
stream: Payload::None,
stream: None,
limit: 32_768,
fut: None,
err: Some(e),
@@ -247,9 +247,8 @@ where
}
}
impl<P, U> Future for UrlEncoded<P, U>
impl<U> Future for UrlEncoded<U>
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
U: DeserializeOwned + 'static,
{
type Item = U;
@@ -274,7 +273,10 @@ where
// future
let encoding = self.encoding;
let fut = std::mem::replace(&mut self.stream, Payload::None)
let fut = self
.stream
.take()
.unwrap()
.from_err()
.fold(BytesMut::with_capacity(8192), move |mut body, chunk| {
if (body.len() + chunk.len()) > limit {
@@ -355,20 +357,20 @@ mod tests {
TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
.header(CONTENT_LENGTH, "xxxx")
.to_http_parts();
let info = block_on(UrlEncoded::<_, Info>::new(&req, &mut pl));
let info = block_on(UrlEncoded::<Info>::new(&req, &mut pl));
assert!(eq(info.err().unwrap(), UrlencodedError::UnknownLength));
let (req, mut pl) =
TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
.header(CONTENT_LENGTH, "1000000")
.to_http_parts();
let info = block_on(UrlEncoded::<_, Info>::new(&req, &mut pl));
let info = block_on(UrlEncoded::<Info>::new(&req, &mut pl));
assert!(eq(info.err().unwrap(), UrlencodedError::Overflow));
let (req, mut pl) = TestRequest::with_header(CONTENT_TYPE, "text/plain")
.header(CONTENT_LENGTH, "10")
.to_http_parts();
let info = block_on(UrlEncoded::<_, Info>::new(&req, &mut pl));
let info = block_on(UrlEncoded::<Info>::new(&req, &mut pl));
assert!(eq(info.err().unwrap(), UrlencodedError::ContentType));
}
@@ -380,7 +382,7 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts();
let info = block_on(UrlEncoded::<_, Info>::new(&req, &mut pl)).unwrap();
let info = block_on(UrlEncoded::<Info>::new(&req, &mut pl)).unwrap();
assert_eq!(
info,
Info {
@@ -396,7 +398,7 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts();
let info = block_on(UrlEncoded::<_, Info>::new(&req, &mut pl)).unwrap();
let info = block_on(UrlEncoded::<Info>::new(&req, &mut pl)).unwrap();
assert_eq!(
info,
Info {

View File

@@ -3,7 +3,7 @@
use std::rc::Rc;
use std::{fmt, ops};
use bytes::{Bytes, BytesMut};
use bytes::BytesMut;
use futures::{Future, Poll, Stream};
use serde::de::DeserializeOwned;
use serde::Serialize;
@@ -12,7 +12,8 @@ use serde_json;
use actix_http::http::{header::CONTENT_LENGTH, StatusCode};
use actix_http::{HttpMessage, Payload, Response};
use crate::error::{Error, JsonPayloadError, PayloadError};
use crate::dev::Decompress;
use crate::error::{Error, JsonPayloadError};
use crate::extract::FromRequest;
use crate::request::HttpRequest;
use crate::responder::Responder;
@@ -163,16 +164,16 @@ impl<T: Serialize> Responder for Json<T> {
/// );
/// }
/// ```
impl<T, P> FromRequest<P> for Json<T>
impl<T> FromRequest for Json<T>
where
T: DeserializeOwned + 'static,
P: Stream<Item = Bytes, Error = crate::error::PayloadError> + 'static,
{
type Config = JsonConfig;
type Error = Error;
type Future = Box<Future<Item = Self, Error = Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let req2 = req.clone();
let (limit, err) = req
.route_data::<JsonConfig>()
@@ -205,7 +206,7 @@ where
///
/// ```rust
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{error, web, App, HttpResponse};
/// use actix_web::{error, web, App, FromRequest, HttpResponse};
///
/// #[derive(Deserialize)]
/// struct Info {
@@ -222,10 +223,12 @@ where
/// web::resource("/index.html").route(
/// web::post().data(
/// // change json extractor configuration
/// web::JsonConfig::default().limit(4096)
/// web::Json::<Info>::configure(|cfg| {
/// cfg.limit(4096)
/// .error_handler(|err, req| { // <- create custom error response
/// error::InternalError::from_response(
/// err, HttpResponse::Conflict().finish()).into()
/// })
/// }))
/// .to(index))
/// );
@@ -270,21 +273,20 @@ impl Default for JsonConfig {
///
/// * content type is not `application/json`
/// * content length is greater than 256k
pub struct JsonBody<P, U> {
pub struct JsonBody<U> {
limit: usize,
length: Option<usize>,
stream: Payload<P>,
stream: Option<Decompress<Payload>>,
err: Option<JsonPayloadError>,
fut: Option<Box<Future<Item = U, Error = JsonPayloadError>>>,
}
impl<P, U> JsonBody<P, U>
impl<U> JsonBody<U>
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
U: DeserializeOwned + 'static,
{
/// Create `JsonBody` for request.
pub fn new(req: &HttpRequest, payload: &mut Payload<P>) -> Self {
pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self {
// check content-type
let json = if let Ok(Some(mime)) = req.mime_type() {
mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON)
@@ -295,7 +297,7 @@ where
return JsonBody {
limit: 262_144,
length: None,
stream: Payload::None,
stream: None,
fut: None,
err: Some(JsonPayloadError::ContentType),
};
@@ -309,11 +311,12 @@ where
}
}
}
let payload = Decompress::from_headers(payload.take(), req.headers());
JsonBody {
limit: 262_144,
length: len,
stream: payload.take(),
stream: Some(payload),
fut: None,
err: None,
}
@@ -326,9 +329,8 @@ where
}
}
impl<P, U> Future for JsonBody<P, U>
impl<U> Future for JsonBody<U>
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
U: DeserializeOwned + 'static,
{
type Item = U;
@@ -350,7 +352,10 @@ where
}
}
let fut = std::mem::replace(&mut self.stream, Payload::None)
let fut = self
.stream
.take()
.unwrap()
.from_err()
.fold(BytesMut::with_capacity(8192), move |mut body, chunk| {
if (body.len() + chunk.len()) > limit {
@@ -508,7 +513,7 @@ mod tests {
#[test]
fn test_json_body() {
let (req, mut pl) = TestRequest::default().to_http_parts();
let json = block_on(JsonBody::<_, MyObject>::new(&req, &mut pl));
let json = block_on(JsonBody::<MyObject>::new(&req, &mut pl));
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
@@ -517,7 +522,7 @@ mod tests {
header::HeaderValue::from_static("application/text"),
)
.to_http_parts();
let json = block_on(JsonBody::<_, MyObject>::new(&req, &mut pl));
let json = block_on(JsonBody::<MyObject>::new(&req, &mut pl));
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
@@ -531,7 +536,7 @@ mod tests {
)
.to_http_parts();
let json = block_on(JsonBody::<_, MyObject>::new(&req, &mut pl).limit(100));
let json = block_on(JsonBody::<MyObject>::new(&req, &mut pl).limit(100));
assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow));
let (req, mut pl) = TestRequest::default()
@@ -546,7 +551,7 @@ mod tests {
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.to_http_parts();
let json = block_on(JsonBody::<_, MyObject>::new(&req, &mut pl));
let json = block_on(JsonBody::<MyObject>::new(&req, &mut pl));
assert_eq!(
json.ok().unwrap(),
MyObject {

View File

@@ -152,15 +152,16 @@ impl<T: fmt::Display> fmt::Display for Path<T> {
/// );
/// }
/// ```
impl<T, P> FromRequest<P> for Path<T>
impl<T> FromRequest for Path<T>
where
T: de::DeserializeOwned,
{
type Config = ();
type Error = Error;
type Future = Result<Self, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
de::Deserialize::deserialize(PathDeserializer::new(req.match_info()))
.map(|inner| Path { inner })
.map_err(ErrorNotFound)

View File

@@ -44,7 +44,7 @@ use crate::request::HttpRequest;
/// );
/// }
/// ```
pub struct Payload(crate::dev::Payload<Box<Stream<Item = Bytes, Error = PayloadError>>>);
pub struct Payload(crate::dev::Payload);
impl Stream for Payload {
type Item = Bytes;
@@ -85,26 +85,14 @@ impl Stream for Payload {
/// );
/// }
/// ```
impl<P> FromRequest<P> for Payload
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
{
impl FromRequest for Payload {
type Config = PayloadConfig;
type Error = Error;
type Future = Result<Payload, Error>;
#[inline]
fn from_request(_: &HttpRequest, payload: &mut dev::Payload<P>) -> Self::Future {
let pl = match payload.take() {
crate::dev::Payload::Stream(s) => {
let pl: Box<dyn Stream<Item = Bytes, Error = PayloadError>> =
Box::new(s);
crate::dev::Payload::Stream(pl)
}
crate::dev::Payload::None => crate::dev::Payload::None,
crate::dev::Payload::H1(pl) => crate::dev::Payload::H1(pl),
crate::dev::Payload::H2(pl) => crate::dev::Payload::H2(pl),
};
Ok(Payload(pl))
fn from_request(_: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
Ok(Payload(payload.take()))
}
}
@@ -133,16 +121,14 @@ where
/// );
/// }
/// ```
impl<P> FromRequest<P> for Bytes
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
{
impl FromRequest for Bytes {
type Config = PayloadConfig;
type Error = Error;
type Future =
Either<Box<Future<Item = Bytes, Error = Error>>, FutureResult<Bytes, Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut dev::Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
let mut tmp;
let cfg = if let Some(cfg) = req.route_data::<PayloadConfig>() {
cfg
@@ -172,7 +158,7 @@ where
/// ## Example
///
/// ```rust
/// use actix_web::{web, App};
/// use actix_web::{web, App, FromRequest};
///
/// /// extract text data from request
/// fn index(text: String) -> String {
@@ -183,21 +169,21 @@ where
/// let app = App::new().service(
/// web::resource("/index.html").route(
/// web::get()
/// .data(web::PayloadConfig::new(4096)) // <- limit size of the payload
/// .data(String::configure(|cfg| { // <- limit size of the payload
/// cfg.limit(4096)
/// }))
/// .to(index)) // <- register handler with extractor params
/// );
/// }
/// ```
impl<P> FromRequest<P> for String
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
{
impl FromRequest for String {
type Config = PayloadConfig;
type Error = Error;
type Future =
Either<Box<Future<Item = String, Error = Error>>, FutureResult<String, Error>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut dev::Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
let mut tmp;
let cfg = if let Some(cfg) = req.route_data::<PayloadConfig>() {
cfg
@@ -247,7 +233,9 @@ pub struct PayloadConfig {
impl PayloadConfig {
/// Create `PayloadConfig` instance and set max size of payload.
pub fn new(limit: usize) -> Self {
Self::default().limit(limit)
let mut cfg = Self::default();
cfg.limit = limit;
cfg
}
/// Change max size of payload. By default max size is 256Kb
@@ -300,20 +288,17 @@ impl Default for PayloadConfig {
/// By default only 256Kb payload reads to a memory, then
/// `PayloadError::Overflow` get returned. Use `MessageBody::limit()`
/// method to change upper limit.
pub struct HttpMessageBody<P> {
pub struct HttpMessageBody {
limit: usize,
length: Option<usize>,
stream: dev::Payload<P>,
stream: Option<dev::Decompress<dev::Payload>>,
err: Option<PayloadError>,
fut: Option<Box<Future<Item = Bytes, Error = PayloadError>>>,
}
impl<P> HttpMessageBody<P>
where
P: Stream<Item = Bytes, Error = PayloadError>,
{
impl HttpMessageBody {
/// Create `MessageBody` for request.
pub fn new(req: &HttpRequest, payload: &mut dev::Payload<P>) -> HttpMessageBody<P> {
pub fn new(req: &HttpRequest, payload: &mut dev::Payload) -> HttpMessageBody {
let mut len = None;
if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) {
if let Ok(s) = l.to_str() {
@@ -328,7 +313,7 @@ where
}
HttpMessageBody {
stream: payload.take(),
stream: Some(dev::Decompress::from_headers(payload.take(), req.headers())),
limit: 262_144,
length: len,
fut: None,
@@ -344,7 +329,7 @@ where
fn err(e: PayloadError) -> Self {
HttpMessageBody {
stream: dev::Payload::None,
stream: None,
limit: 262_144,
fut: None,
err: Some(e),
@@ -353,10 +338,7 @@ where
}
}
impl<P> Future for HttpMessageBody<P>
where
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
{
impl Future for HttpMessageBody {
type Item = Bytes;
type Error = PayloadError;
@@ -378,7 +360,9 @@ where
// future
let limit = self.limit;
self.fut = Some(Box::new(
std::mem::replace(&mut self.stream, actix_http::Payload::None)
self.stream
.take()
.unwrap()
.from_err()
.fold(BytesMut::with_capacity(8192), move |mut body, chunk| {
if (body.len() + chunk.len()) > limit {

View File

@@ -111,15 +111,16 @@ impl<T: fmt::Display> fmt::Display for Query<T> {
/// .route(web::get().to(index))); // <- use `Query` extractor
/// }
/// ```
impl<T, P> FromRequest<P> for Query<T>
impl<T> FromRequest for Query<T>
where
T: de::DeserializeOwned,
{
type Config = ();
type Error = Error;
type Future = Result<Self, Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload<P>) -> Self::Future {
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
serde_urlencoded::from_str::<T>(req.query_string())
.map(|val| Ok(Query(val)))
.unwrap_or_else(|e| {

View File

@@ -50,7 +50,7 @@ pub use crate::types::*;
/// );
/// }
/// ```
pub fn resource<P: 'static>(path: &str) -> Resource<P> {
pub fn resource(path: &str) -> Resource {
Resource::new(path)
}
@@ -77,12 +77,12 @@ pub fn resource<P: 'static>(path: &str) -> Resource<P> {
/// * /{project_id}/path2
/// * /{project_id}/path3
///
pub fn scope<P: 'static>(path: &str) -> Scope<P> {
pub fn scope(path: &str) -> Scope {
Scope::new(path)
}
/// Create *route* without configuration.
pub fn route<P: 'static>() -> Route<P> {
pub fn route() -> Route {
Route::new()
}
@@ -102,7 +102,7 @@ pub fn route<P: 'static>() -> Route<P> {
/// In the above example, one `GET` route get added:
/// * /{project_id}
///
pub fn get<P: 'static>() -> Route<P> {
pub fn get() -> Route {
Route::new().method(Method::GET)
}
@@ -122,7 +122,7 @@ pub fn get<P: 'static>() -> Route<P> {
/// In the above example, one `POST` route get added:
/// * /{project_id}
///
pub fn post<P: 'static>() -> Route<P> {
pub fn post() -> Route {
Route::new().method(Method::POST)
}
@@ -142,7 +142,7 @@ pub fn post<P: 'static>() -> Route<P> {
/// In the above example, one `PUT` route get added:
/// * /{project_id}
///
pub fn put<P: 'static>() -> Route<P> {
pub fn put() -> Route {
Route::new().method(Method::PUT)
}
@@ -162,7 +162,7 @@ pub fn put<P: 'static>() -> Route<P> {
/// In the above example, one `PATCH` route get added:
/// * /{project_id}
///
pub fn patch<P: 'static>() -> Route<P> {
pub fn patch() -> Route {
Route::new().method(Method::PATCH)
}
@@ -182,7 +182,7 @@ pub fn patch<P: 'static>() -> Route<P> {
/// In the above example, one `DELETE` route get added:
/// * /{project_id}
///
pub fn delete<P: 'static>() -> Route<P> {
pub fn delete() -> Route {
Route::new().method(Method::DELETE)
}
@@ -202,7 +202,7 @@ pub fn delete<P: 'static>() -> Route<P> {
/// In the above example, one `HEAD` route get added:
/// * /{project_id}
///
pub fn head<P: 'static>() -> Route<P> {
pub fn head() -> Route {
Route::new().method(Method::HEAD)
}
@@ -222,7 +222,7 @@ pub fn head<P: 'static>() -> Route<P> {
/// In the above example, one `GET` route get added:
/// * /{project_id}
///
pub fn method<P: 'static>(method: Method) -> Route<P> {
pub fn method(method: Method) -> Route {
Route::new().method(method)
}
@@ -240,10 +240,10 @@ pub fn method<P: 'static>(method: Method) -> Route<P> {
/// web::to(index))
/// );
/// ```
pub fn to<F, I, R, P: 'static>(handler: F) -> Route<P>
pub fn to<F, I, R>(handler: F) -> Route
where
F: Factory<I, R> + 'static,
I: FromRequest<P> + 'static,
I: FromRequest + 'static,
R: Responder + 'static,
{
Route::new().to(handler)
@@ -263,10 +263,10 @@ where
/// web::to_async(index))
/// );
/// ```
pub fn to_async<F, I, R, P: 'static>(handler: F) -> Route<P>
pub fn to_async<F, I, R>(handler: F) -> Route
where
F: AsyncFactory<I, R>,
I: FromRequest<P> + 'static,
I: FromRequest + 'static,
R: IntoFuture + 'static,
R::Item: Into<Response>,
R::Error: Into<Error>,

View File

@@ -16,13 +16,9 @@ use flate2::Compression;
use futures::stream::once;
use rand::{distributions::Alphanumeric, Rng};
use actix_web::middleware::{BodyEncoding, Compress};
use actix_web::{http, test, web, App, HttpResponse, HttpServer};
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
use actix_web::middleware::encoding;
#[cfg(any(feature = "brotli", feature = "flate2-zlib", feature = "flate2-rust"))]
use actix_web::middleware::encoding::BodyEncoding;
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
@@ -68,7 +64,7 @@ fn test_body_gzip() {
let mut srv = TestServer::new(|| {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Gzip))
.wrap(Compress::new(ContentEncoding::Gzip))
.service(web::resource("/").route(web::to(|| Response::Ok().body(STR)))),
)
});
@@ -99,13 +95,11 @@ fn test_body_encoding_override() {
let mut srv = TestServer::new(|| {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Gzip))
.wrap(Compress::new(ContentEncoding::Gzip))
.service(web::resource("/").route(web::to(|| {
use actix_web::middleware::encoding::BodyEncoding;
Response::Ok().encoding(ContentEncoding::Deflate).body(STR)
})))
.service(web::resource("/raw").route(web::to(|| {
use actix_web::middleware::encoding::BodyEncoding;
let body = actix_web::dev::Body::Bytes(STR.into());
let mut response =
Response::with_body(actix_web::http::StatusCode::OK, body);
@@ -168,7 +162,7 @@ fn test_body_gzip_large() {
let data = srv_data.clone();
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Gzip))
.wrap(Compress::new(ContentEncoding::Gzip))
.service(
web::resource("/")
.route(web::to(move || Response::Ok().body(data.clone()))),
@@ -209,7 +203,7 @@ fn test_body_gzip_large_random() {
let data = srv_data.clone();
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Gzip))
.wrap(Compress::new(ContentEncoding::Gzip))
.service(
web::resource("/")
.route(web::to(move || Response::Ok().body(data.clone()))),
@@ -244,7 +238,7 @@ fn test_body_chunked_implicit() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Gzip))
.wrap(Compress::new(ContentEncoding::Gzip))
.service(web::resource("/").route(web::get().to(move || {
Response::Ok().streaming(once(Ok::<_, Error>(Bytes::from_static(
STR.as_ref(),
@@ -281,15 +275,12 @@ fn test_body_chunked_implicit() {
#[cfg(feature = "brotli")]
fn test_body_br_streaming() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Br))
.service(web::resource("/").route(web::to(move || {
Response::Ok().streaming(once(Ok::<_, Error>(Bytes::from_static(
STR.as_ref(),
))))
}))),
)
h1::H1Service::new(App::new().wrap(Compress::new(ContentEncoding::Br)).service(
web::resource("/").route(web::to(move || {
Response::Ok()
.streaming(once(Ok::<_, Error>(Bytes::from_static(STR.as_ref()))))
})),
))
});
let mut response = srv
@@ -361,7 +352,7 @@ fn test_body_deflate() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Deflate))
.wrap(Compress::new(ContentEncoding::Deflate))
.service(
web::resource("/").route(web::to(move || Response::Ok().body(STR))),
),
@@ -392,13 +383,9 @@ fn test_body_deflate() {
#[cfg(any(feature = "brotli"))]
fn test_body_brotli() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new()
.wrap(encoding::Compress::new(ContentEncoding::Br))
.service(
h1::H1Service::new(App::new().wrap(Compress::new(ContentEncoding::Br)).service(
web::resource("/").route(web::to(move || Response::Ok().body(STR))),
),
)
))
});
// client request
@@ -427,7 +414,7 @@ fn test_body_brotli() {
fn test_encoding() {
let mut srv = TestServer::new(move || {
HttpService::new(
App::new().enable_encoding().service(
App::new().wrap(Compress::default()).service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -456,7 +443,7 @@ fn test_encoding() {
fn test_gzip_encoding() {
let mut srv = TestServer::new(move || {
HttpService::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -486,7 +473,7 @@ fn test_gzip_encoding_large() {
let data = STR.repeat(10);
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -520,7 +507,7 @@ fn test_reading_gzip_encoding_large_random() {
let mut srv = TestServer::new(move || {
HttpService::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -550,7 +537,7 @@ fn test_reading_gzip_encoding_large_random() {
fn test_reading_deflate_encoding() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -580,7 +567,7 @@ fn test_reading_deflate_encoding_large() {
let data = STR.repeat(10);
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -614,7 +601,7 @@ fn test_reading_deflate_encoding_large_random() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -644,7 +631,7 @@ fn test_reading_deflate_encoding_large_random() {
fn test_brotli_encoding() {
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),
@@ -674,7 +661,7 @@ fn test_brotli_encoding_large() {
let data = STR.repeat(10);
let mut srv = TestServer::new(move || {
h1::H1Service::new(
App::new().chain(encoding::Decompress::new()).service(
App::new().service(
web::resource("/")
.route(web::to(move |body: Bytes| Response::Ok().body(body))),
),