mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
move fs to separate crate
This commit is contained in:
parent
2d7293aaf8
commit
e6d04d24cc
@ -23,6 +23,12 @@ codecov = { repository = "actix/actix-web2", branch = "master", service = "githu
|
|||||||
name = "actix_web"
|
name = "actix_web"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
".",
|
||||||
|
"actix-web-fs",
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["brotli", "flate2-c"]
|
default = ["brotli", "flate2-c"]
|
||||||
|
|
||||||
|
14
Makefile
14
Makefile
@ -1,14 +0,0 @@
|
|||||||
.PHONY: default build test doc book clean
|
|
||||||
|
|
||||||
CARGO_FLAGS := --features "$(FEATURES) alpn tls"
|
|
||||||
|
|
||||||
default: test
|
|
||||||
|
|
||||||
build:
|
|
||||||
cargo build $(CARGO_FLAGS)
|
|
||||||
|
|
||||||
test: build clippy
|
|
||||||
cargo test $(CARGO_FLAGS)
|
|
||||||
|
|
||||||
doc: build
|
|
||||||
cargo doc --no-deps $(CARGO_FLAGS)
|
|
5
actix-web-fs/CHANGES.md
Normal file
5
actix-web-fs/CHANGES.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.0] - 2018-10-x
|
||||||
|
|
||||||
|
* Initial impl
|
42
actix-web-fs/Cargo.toml
Normal file
42
actix-web-fs/Cargo.toml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[package]
|
||||||
|
name = "actix-web-fs"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
|
description = "Static files support for Actix web."
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["actix", "http", "async", "futures"]
|
||||||
|
homepage = "https://actix.rs"
|
||||||
|
repository = "https://github.com/actix/actix-web.git"
|
||||||
|
documentation = "https://actix.rs/api/actix-web/stable/actix_web/"
|
||||||
|
categories = ["asynchronous", "web-programming::http-server"]
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
workspace = ".."
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "actix_web_fs"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = { path=".." }
|
||||||
|
actix-http = { git = "https://github.com/actix/actix-http.git" }
|
||||||
|
actix-service = { git = "https://github.com/actix/actix-net.git" }
|
||||||
|
|
||||||
|
bytes = "0.4"
|
||||||
|
futures = "0.1"
|
||||||
|
derive_more = "0.14"
|
||||||
|
log = "0.4"
|
||||||
|
mime = "0.3"
|
||||||
|
mime_guess = "2.0.0-alpha"
|
||||||
|
percent-encoding = "1.0"
|
||||||
|
v_htmlescape = "0.4"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
actix-rt = "0.1.0"
|
||||||
|
#actix-server = { version="0.2", features=["ssl"] }
|
||||||
|
actix-server = { git = "https://github.com/actix/actix-net.git", features=["ssl"] }
|
||||||
|
actix-http = { git = "https://github.com/actix/actix-http.git", features=["ssl"] }
|
||||||
|
actix-http-test = { git = "https://github.com/actix/actix-http.git", features=["ssl"] }
|
||||||
|
rand = "0.6"
|
||||||
|
env_logger = "0.6"
|
||||||
|
serde_derive = "1.0"
|
82
actix-web-fs/README.md
Normal file
82
actix-web-fs/README.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Actix web [![Build Status](https://travis-ci.org/actix/actix-web.svg?branch=master)](https://travis-ci.org/actix/actix-web) [![Build status](https://ci.appveyor.com/api/projects/status/kkdb4yce7qhm5w85/branch/master?svg=true)](https://ci.appveyor.com/project/fafhrd91/actix-web-hdy9d/branch/master) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) [![crates.io](https://meritbadge.herokuapp.com/actix-web)](https://crates.io/crates/actix-web) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
Actix web is a simple, pragmatic and extremely fast web framework for Rust.
|
||||||
|
|
||||||
|
* Supported *HTTP/1.x* and [*HTTP/2.0*](https://actix.rs/docs/http2/) protocols
|
||||||
|
* Streaming and pipelining
|
||||||
|
* Keep-alive and slow requests handling
|
||||||
|
* Client/server [WebSockets](https://actix.rs/docs/websockets/) support
|
||||||
|
* Transparent content compression/decompression (br, gzip, deflate)
|
||||||
|
* Configurable [request routing](https://actix.rs/docs/url-dispatch/)
|
||||||
|
* Multipart streams
|
||||||
|
* Static assets
|
||||||
|
* SSL support with OpenSSL or `native-tls`
|
||||||
|
* Middlewares ([Logger, Session, CORS, CSRF, etc](https://actix.rs/docs/middleware/))
|
||||||
|
* Includes an asynchronous [HTTP client](https://actix.rs/actix-web/actix_web/client/index.html)
|
||||||
|
* Built on top of [Actix actor framework](https://github.com/actix/actix)
|
||||||
|
* Experimental [Async/Await](https://github.com/mehcode/actix-web-async-await) support.
|
||||||
|
|
||||||
|
## Documentation & community resources
|
||||||
|
|
||||||
|
* [User Guide](https://actix.rs/docs/)
|
||||||
|
* [API Documentation (Development)](https://actix.rs/actix-web/actix_web/)
|
||||||
|
* [API Documentation (Releases)](https://actix.rs/api/actix-web/stable/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.31 or later
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
extern crate actix_web;
|
||||||
|
use actix_web::{http, server, App, Path, Responder};
|
||||||
|
|
||||||
|
fn index(info: Path<(u32, String)>) -> impl Responder {
|
||||||
|
format!("Hello {}! id:{}", info.1, info.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
server::new(
|
||||||
|
|| App::new()
|
||||||
|
.route("/{id}/{name}/index.html", http::Method::GET, index))
|
||||||
|
.bind("127.0.0.1:8080").unwrap()
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### More examples
|
||||||
|
|
||||||
|
* [Basics](https://github.com/actix/examples/tree/master/basics/)
|
||||||
|
* [Stateful](https://github.com/actix/examples/tree/master/state/)
|
||||||
|
* [Protobuf support](https://github.com/actix/examples/tree/master/protobuf/)
|
||||||
|
* [Multipart streams](https://github.com/actix/examples/tree/master/multipart/)
|
||||||
|
* [Simple websocket](https://github.com/actix/examples/tree/master/websocket/)
|
||||||
|
* [Tera](https://github.com/actix/examples/tree/master/template_tera/) /
|
||||||
|
[Askama](https://github.com/actix/examples/tree/master/template_askama/) templates
|
||||||
|
* [Diesel integration](https://github.com/actix/examples/tree/master/diesel/)
|
||||||
|
* [r2d2](https://github.com/actix/examples/tree/master/r2d2/)
|
||||||
|
* [SSL / HTTP/2.0](https://github.com/actix/examples/tree/master/tls/)
|
||||||
|
* [Tcp/Websocket chat](https://github.com/actix/examples/tree/master/websocket-chat/)
|
||||||
|
* [Json](https://github.com/actix/examples/tree/master/json/)
|
||||||
|
|
||||||
|
You may consider checking out
|
||||||
|
[this directory](https://github.com/actix/examples/tree/master/) for more examples.
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
|
||||||
|
* [TechEmpower Framework Benchmark](https://www.techempower.com/benchmarks/#section=data-r16&hw=ph&test=plaintext)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under either of
|
||||||
|
|
||||||
|
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
|
||||||
|
* MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
|
||||||
|
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Contribution to the actix-web crate is organized under the terms of the
|
||||||
|
Contributor Covenant, the maintainer of actix-web, @fafhrd91, promises to
|
||||||
|
intervene to uphold that code of conduct.
|
@ -27,15 +27,14 @@ use actix_http::http::header::{
|
|||||||
};
|
};
|
||||||
use actix_http::http::{ContentEncoding, Method, StatusCode};
|
use actix_http::http::{ContentEncoding, Method, StatusCode};
|
||||||
use actix_http::{HttpMessage, Response};
|
use actix_http::{HttpMessage, Response};
|
||||||
|
use actix_service::boxed::BoxedNewService;
|
||||||
use actix_service::{NewService, Service};
|
use actix_service::{NewService, Service};
|
||||||
|
use actix_web::{
|
||||||
|
blocking, FromRequest, HttpRequest, Responder, ServiceRequest, ServiceResponse,
|
||||||
|
};
|
||||||
use futures::future::{err, ok, FutureResult};
|
use futures::future::{err, ok, FutureResult};
|
||||||
|
|
||||||
use crate::blocking;
|
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||||
use crate::handler::FromRequest;
|
|
||||||
use crate::helpers::HttpDefaultNewService;
|
|
||||||
use crate::request::HttpRequest;
|
|
||||||
use crate::responder::Responder;
|
|
||||||
use crate::service::{ServiceRequest, ServiceResponse};
|
|
||||||
|
|
||||||
///Describes `StaticFiles` configiration
|
///Describes `StaticFiles` configiration
|
||||||
///
|
///
|
||||||
@ -101,6 +100,7 @@ pub trait StaticFileConfig: Default {
|
|||||||
///[StaticFileConfig](trait.StaticFileConfig.html)
|
///[StaticFileConfig](trait.StaticFileConfig.html)
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DefaultConfig;
|
pub struct DefaultConfig;
|
||||||
|
|
||||||
impl StaticFileConfig for DefaultConfig {}
|
impl StaticFileConfig for DefaultConfig {}
|
||||||
|
|
||||||
/// Return the MIME type associated with a filename extension (case-insensitive).
|
/// Return the MIME type associated with a filename extension (case-insensitive).
|
||||||
@ -716,9 +716,7 @@ pub struct StaticFiles<S, C = DefaultConfig> {
|
|||||||
directory: PathBuf,
|
directory: PathBuf,
|
||||||
index: Option<String>,
|
index: Option<String>,
|
||||||
show_index: bool,
|
show_index: bool,
|
||||||
default: Rc<
|
default: Rc<RefCell<Option<Rc<HttpNewService<S>>>>>,
|
||||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<S>, ServiceResponse>>>>,
|
|
||||||
>,
|
|
||||||
renderer: Rc<DirectoryRenderer>,
|
renderer: Rc<DirectoryRenderer>,
|
||||||
_chunk_size: usize,
|
_chunk_size: usize,
|
||||||
_follow_symlinks: bool,
|
_follow_symlinks: bool,
|
||||||
@ -817,9 +815,7 @@ pub struct StaticFilesService<S, C = DefaultConfig> {
|
|||||||
directory: PathBuf,
|
directory: PathBuf,
|
||||||
index: Option<String>,
|
index: Option<String>,
|
||||||
show_index: bool,
|
show_index: bool,
|
||||||
default: Rc<
|
default: Rc<RefCell<Option<Rc<HttpNewService<S>>>>>,
|
||||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<S>, ServiceResponse>>>>,
|
|
||||||
>,
|
|
||||||
renderer: Rc<DirectoryRenderer>,
|
renderer: Rc<DirectoryRenderer>,
|
||||||
_chunk_size: usize,
|
_chunk_size: usize,
|
||||||
_follow_symlinks: bool,
|
_follow_symlinks: bool,
|
||||||
@ -838,8 +834,8 @@ impl<S: 'static, C: StaticFileConfig> Service for StaticFilesService<S, C> {
|
|||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
let mut req = req;
|
let mut req = req;
|
||||||
let real_path = match PathBuf::from_request(&mut req).poll() {
|
let real_path = match PathBufWrp::from_request(&mut req).poll() {
|
||||||
Ok(Async::Ready(item)) => item,
|
Ok(Async::Ready(item)) => item.0,
|
||||||
Ok(Async::NotReady) => unreachable!(),
|
Ok(Async::NotReady) => unreachable!(),
|
||||||
Err(e) => return err(Error::from(e)),
|
Err(e) => return err(Error::from(e)),
|
||||||
};
|
};
|
||||||
@ -888,7 +884,9 @@ impl<S: 'static, C: StaticFileConfig> Service for StaticFilesService<S, C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> FromRequest<P> for PathBuf {
|
struct PathBufWrp(PathBuf);
|
||||||
|
|
||||||
|
impl<P> FromRequest<P> for PathBufWrp {
|
||||||
type Error = UriSegmentError;
|
type Error = UriSegmentError;
|
||||||
type Future = FutureResult<Self, Self::Error>;
|
type Future = FutureResult<Self, Self::Error>;
|
||||||
|
|
||||||
@ -917,7 +915,7 @@ impl<P> FromRequest<P> for PathBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok(buf)
|
ok(PathBufWrp(buf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ use futures::IntoFuture;
|
|||||||
|
|
||||||
use actix_http::{h1, http::Method, Response};
|
use actix_http::{h1, http::Method, Response};
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use actix_web2::{middleware, App, Error, HttpRequest, Resource};
|
use actix_web::{middleware, App, Error, HttpRequest, Resource};
|
||||||
|
|
||||||
fn index(req: HttpRequest) -> &'static str {
|
fn index(req: HttpRequest) -> &'static str {
|
||||||
println!("REQ: {:?}", req);
|
println!("REQ: {:?}", req);
|
||||||
|
118
src/app.rs
118
src/app.rs
@ -5,6 +5,7 @@ use std::rc::Rc;
|
|||||||
use actix_http::body::{Body, MessageBody};
|
use actix_http::body::{Body, MessageBody};
|
||||||
use actix_http::{Extensions, PayloadStream, Request, Response};
|
use actix_http::{Extensions, PayloadStream, Request, Response};
|
||||||
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
|
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
|
||||||
|
use actix_service::boxed::{self, BoxedNewService, BoxedService};
|
||||||
use actix_service::{
|
use actix_service::{
|
||||||
AndThenNewService, ApplyNewService, IntoNewService, IntoNewTransform, NewService,
|
AndThenNewService, ApplyNewService, IntoNewService, IntoNewTransform, NewService,
|
||||||
NewTransform, Service,
|
NewTransform, Service,
|
||||||
@ -12,13 +13,12 @@ use actix_service::{
|
|||||||
use futures::future::{ok, Either, FutureResult};
|
use futures::future::{ok, Either, FutureResult};
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::helpers::{
|
|
||||||
BoxedHttpNewService, BoxedHttpService, DefaultNewService, HttpDefaultNewService,
|
|
||||||
};
|
|
||||||
use crate::resource::Resource;
|
use crate::resource::Resource;
|
||||||
use crate::service::{ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceRequest, ServiceResponse};
|
||||||
use crate::state::{State, StateFactory, StateFactoryResult};
|
use crate::state::{State, StateFactory, StateFactoryResult};
|
||||||
|
|
||||||
|
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
|
||||||
|
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||||
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>;
|
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>;
|
||||||
|
|
||||||
pub trait HttpServiceFactory<Request> {
|
pub trait HttpServiceFactory<Request> {
|
||||||
@ -31,18 +31,9 @@ pub trait HttpServiceFactory<Request> {
|
|||||||
|
|
||||||
/// Application builder
|
/// Application builder
|
||||||
pub struct App<P, B, T> {
|
pub struct App<P, B, T> {
|
||||||
services: Vec<(
|
services: Vec<(ResourceDef, HttpNewService<P>)>,
|
||||||
ResourceDef,
|
default: Option<Rc<HttpNewService<P>>>,
|
||||||
BoxedHttpNewService<ServiceRequest<P>, ServiceResponse>,
|
defaults: Vec<Rc<RefCell<Option<Rc<HttpNewService<P>>>>>>,
|
||||||
)>,
|
|
||||||
default: Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>,
|
|
||||||
defaults: Vec<
|
|
||||||
Rc<
|
|
||||||
RefCell<
|
|
||||||
Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
endpoint: T,
|
endpoint: T,
|
||||||
factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
||||||
extensions: Extensions,
|
extensions: Extensions,
|
||||||
@ -181,10 +172,8 @@ where
|
|||||||
let rdef = ResourceDef::new(path);
|
let rdef = ResourceDef::new(path);
|
||||||
let resource = f(Resource::new());
|
let resource = f(Resource::new());
|
||||||
self.defaults.push(resource.get_default());
|
self.defaults.push(resource.get_default());
|
||||||
self.services.push((
|
self.services
|
||||||
rdef,
|
.push((rdef, boxed::new_service(resource.into_new_service())));
|
||||||
Box::new(HttpNewService::new(resource.into_new_service())),
|
|
||||||
));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,9 +192,9 @@ where
|
|||||||
> + 'static,
|
> + 'static,
|
||||||
{
|
{
|
||||||
// create and configure default resource
|
// create and configure default resource
|
||||||
self.default = Some(Rc::new(Box::new(DefaultNewService::new(
|
self.default = Some(Rc::new(boxed::new_service(
|
||||||
f(Resource::new()).into_new_service(),
|
f(Resource::new()).into_new_service().map_init_err(|_| ()),
|
||||||
))));
|
)));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -223,7 +212,7 @@ where
|
|||||||
{
|
{
|
||||||
self.services.push((
|
self.services.push((
|
||||||
rdef.into(),
|
rdef.into(),
|
||||||
Box::new(HttpNewService::new(factory.into_new_service())),
|
boxed::new_service(factory.into_new_service().map_init_err(|_| ())),
|
||||||
));
|
));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -422,15 +411,10 @@ impl<P> Service for AppStateService<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppFactory<P> {
|
pub struct AppFactory<P> {
|
||||||
services: Rc<
|
services: Rc<Vec<(ResourceDef, HttpNewService<P>)>>,
|
||||||
Vec<(
|
|
||||||
ResourceDef,
|
|
||||||
BoxedHttpNewService<ServiceRequest<P>, ServiceResponse>,
|
|
||||||
)>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> NewService for AppFactory<P> {
|
impl<P: 'static> NewService for AppFactory<P> {
|
||||||
type Request = ServiceRequest<P>;
|
type Request = ServiceRequest<P>;
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
@ -454,8 +438,7 @@ impl<P> NewService for AppFactory<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type HttpServiceFut<P> =
|
type HttpServiceFut<P> = Box<Future<Item = HttpService<P>, Error = ()>>;
|
||||||
Box<Future<Item = BoxedHttpService<ServiceRequest<P>, ServiceResponse>, Error = ()>>;
|
|
||||||
|
|
||||||
/// Create app service
|
/// Create app service
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -465,10 +448,7 @@ pub struct CreateAppService<P> {
|
|||||||
|
|
||||||
enum CreateAppServiceItem<P> {
|
enum CreateAppServiceItem<P> {
|
||||||
Future(Option<ResourceDef>, HttpServiceFut<P>),
|
Future(Option<ResourceDef>, HttpServiceFut<P>),
|
||||||
Service(
|
Service(ResourceDef, HttpService<P>),
|
||||||
ResourceDef,
|
|
||||||
BoxedHttpService<ServiceRequest<P>, ServiceResponse>,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> Future for CreateAppService<P> {
|
impl<P> Future for CreateAppService<P> {
|
||||||
@ -522,7 +502,7 @@ impl<P> Future for CreateAppService<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppService<P> {
|
pub struct AppService<P> {
|
||||||
router: Router<BoxedHttpService<ServiceRequest<P>, ServiceResponse>>,
|
router: Router<HttpService<P>>,
|
||||||
ready: Option<(ServiceRequest<P>, ResourceInfo)>,
|
ready: Option<(ServiceRequest<P>, ResourceInfo)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,68 +541,6 @@ impl Future for AppServiceResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HttpNewService<P: 'static, T: NewService<Request = ServiceRequest<P>>>(T);
|
|
||||||
|
|
||||||
impl<P, T> HttpNewService<P, T>
|
|
||||||
where
|
|
||||||
T: NewService<Request = ServiceRequest<P>, Response = ServiceResponse, Error = ()>,
|
|
||||||
T::Future: 'static,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
pub fn new(service: T) -> Self {
|
|
||||||
HttpNewService(service)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: 'static, T> NewService for HttpNewService<P, T>
|
|
||||||
where
|
|
||||||
T: NewService<Request = ServiceRequest<P>, Response = ServiceResponse, Error = ()>,
|
|
||||||
T::Future: 'static,
|
|
||||||
T::Service: 'static,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
type Request = ServiceRequest<P>;
|
|
||||||
type Response = ServiceResponse;
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = BoxedHttpService<ServiceRequest<P>, Self::Response>;
|
|
||||||
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
|
|
||||||
|
|
||||||
fn new_service(&self, _: &()) -> Self::Future {
|
|
||||||
Box::new(self.0.new_service(&()).map_err(|_| ()).and_then(|service| {
|
|
||||||
let service: BoxedHttpService<_, _> = Box::new(HttpServiceWrapper {
|
|
||||||
service,
|
|
||||||
_t: PhantomData,
|
|
||||||
});
|
|
||||||
Ok(service)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HttpServiceWrapper<T: Service, P> {
|
|
||||||
service: T,
|
|
||||||
_t: PhantomData<(P,)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, P> Service for HttpServiceWrapper<T, P>
|
|
||||||
where
|
|
||||||
T::Future: 'static,
|
|
||||||
T: Service<Request = ServiceRequest<P>, Response = ServiceResponse, Error = ()>,
|
|
||||||
{
|
|
||||||
type Request = ServiceRequest<P>;
|
|
||||||
type Response = ServiceResponse;
|
|
||||||
type Error = ();
|
|
||||||
type Future = BoxedResponse;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
self.service.poll_ready().map_err(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
|
||||||
Box::new(self.service.call(req))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct AppEntry<P> {
|
pub struct AppEntry<P> {
|
||||||
factory: Rc<RefCell<Option<AppFactory<P>>>>,
|
factory: Rc<RefCell<Option<AppFactory<P>>>>,
|
||||||
@ -634,7 +552,7 @@ impl<P> AppEntry<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> NewService for AppEntry<P> {
|
impl<P: 'static> NewService for AppEntry<P> {
|
||||||
type Request = ServiceRequest<P>;
|
type Request = ServiceRequest<P>;
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
@ -1,240 +0,0 @@
|
|||||||
use std::marker::PhantomData;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use actix_codec::Framed;
|
|
||||||
use actix_http::h1::Codec;
|
|
||||||
use actix_http::{Request, Response, SendResponse};
|
|
||||||
use actix_router::{Path, Router, Url};
|
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
|
||||||
use actix_utils::cloneable::CloneableService;
|
|
||||||
use futures::{Async, Future, Poll};
|
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
|
||||||
|
|
||||||
use crate::app::{HttpServiceFactory, State};
|
|
||||||
use crate::framed_handler::FramedRequest;
|
|
||||||
use crate::helpers::{BoxedHttpNewService, BoxedHttpService, HttpNewService};
|
|
||||||
use crate::request::Request as WebRequest;
|
|
||||||
|
|
||||||
pub type FRequest<T> = (Request, Framed<T, Codec>);
|
|
||||||
type BoxedResponse = Box<Future<Item = (), Error = ()>>;
|
|
||||||
|
|
||||||
/// Application builder
|
|
||||||
pub struct FramedApp<T, S = ()> {
|
|
||||||
services: Vec<(String, BoxedHttpNewService<FramedRequest<S, T>, ()>)>,
|
|
||||||
state: State<S>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static> FramedApp<T, ()> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
FramedApp {
|
|
||||||
services: Vec::new(),
|
|
||||||
state: State::new(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static, S: 'static> FramedApp<T, S> {
|
|
||||||
pub fn with(state: S) -> FramedApp<T, S> {
|
|
||||||
FramedApp {
|
|
||||||
services: Vec::new(),
|
|
||||||
state: State::new(state),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn service<U>(mut self, factory: U) -> Self
|
|
||||||
where
|
|
||||||
U: HttpServiceFactory<S>,
|
|
||||||
U::Factory: NewService<Request = FramedRequest<S, T>, Response = ()> + 'static,
|
|
||||||
<U::Factory as NewService>::Future: 'static,
|
|
||||||
<U::Factory as NewService>::Service: Service<Request = FramedRequest<S, T>>,
|
|
||||||
<<U::Factory as NewService>::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
let path = factory.path().to_string();
|
|
||||||
self.services.push((
|
|
||||||
path,
|
|
||||||
Box::new(HttpNewService::new(factory.create(self.state.clone()))),
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_service<U>(&mut self, factory: U)
|
|
||||||
where
|
|
||||||
U: HttpServiceFactory<S>,
|
|
||||||
U::Factory: NewService<Request = FramedRequest<S, T>, Response = ()> + 'static,
|
|
||||||
<U::Factory as NewService>::Future: 'static,
|
|
||||||
<U::Factory as NewService>::Service: Service<Request = FramedRequest<S, T>>,
|
|
||||||
<<U::Factory as NewService>::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
let path = factory.path().to_string();
|
|
||||||
self.services.push((
|
|
||||||
path,
|
|
||||||
Box::new(HttpNewService::new(factory.create(self.state.clone()))),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static, S: 'static> IntoNewService<FramedAppFactory<S, T>> for FramedApp<T, S>
|
|
||||||
where
|
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
{
|
|
||||||
fn into_new_service(self) -> FramedAppFactory<S, T> {
|
|
||||||
FramedAppFactory {
|
|
||||||
state: self.state,
|
|
||||||
services: Rc::new(self.services),
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct FramedAppFactory<S, T> {
|
|
||||||
state: State<S>,
|
|
||||||
services: Rc<Vec<(String, BoxedHttpNewService<FramedRequest<S, T>, ()>)>>,
|
|
||||||
_t: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: 'static> NewService for FramedAppFactory<S, T>
|
|
||||||
where
|
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
{
|
|
||||||
type Request = FRequest<T>;
|
|
||||||
type Response = ();
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = CloneableService<FramedAppService<S, T>>;
|
|
||||||
type Future = CreateService<S, T>;
|
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
|
||||||
CreateService {
|
|
||||||
fut: self
|
|
||||||
.services
|
|
||||||
.iter()
|
|
||||||
.map(|(path, service)| {
|
|
||||||
CreateServiceItem::Future(Some(path.clone()), service.new_service())
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
state: self.state.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct CreateService<S, T> {
|
|
||||||
fut: Vec<CreateServiceItem<S, T>>,
|
|
||||||
state: State<S>,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CreateServiceItem<S, T> {
|
|
||||||
Future(
|
|
||||||
Option<String>,
|
|
||||||
Box<Future<Item = BoxedHttpService<FramedRequest<S, T>, ()>, Error = ()>>,
|
|
||||||
),
|
|
||||||
Service(String, BoxedHttpService<FramedRequest<S, T>, ()>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: 'static> Future for CreateService<S, T>
|
|
||||||
where
|
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
{
|
|
||||||
type Item = CloneableService<FramedAppService<S, T>>;
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
let mut done = true;
|
|
||||||
|
|
||||||
// poll http services
|
|
||||||
for item in &mut self.fut {
|
|
||||||
let res = match item {
|
|
||||||
CreateServiceItem::Future(ref mut path, ref mut fut) => {
|
|
||||||
match fut.poll()? {
|
|
||||||
Async::Ready(service) => Some((path.take().unwrap(), service)),
|
|
||||||
Async::NotReady => {
|
|
||||||
done = false;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CreateServiceItem::Service(_, _) => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((path, service)) = res {
|
|
||||||
*item = CreateServiceItem::Service(path, service);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if done {
|
|
||||||
let router = self
|
|
||||||
.fut
|
|
||||||
.drain(..)
|
|
||||||
.fold(Router::build(), |mut router, item| {
|
|
||||||
match item {
|
|
||||||
CreateServiceItem::Service(path, service) => {
|
|
||||||
router.path(&path, service)
|
|
||||||
}
|
|
||||||
CreateServiceItem::Future(_, _) => unreachable!(),
|
|
||||||
}
|
|
||||||
router
|
|
||||||
});
|
|
||||||
Ok(Async::Ready(CloneableService::new(FramedAppService {
|
|
||||||
router: router.finish(),
|
|
||||||
state: self.state.clone(),
|
|
||||||
// default: self.default.take().expect("something is wrong"),
|
|
||||||
})))
|
|
||||||
} else {
|
|
||||||
Ok(Async::NotReady)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedAppService<S, T> {
|
|
||||||
state: State<S>,
|
|
||||||
router: Router<BoxedHttpService<FramedRequest<S, T>, ()>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: 'static> Service for FramedAppService<S, T>
|
|
||||||
where
|
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
{
|
|
||||||
type Request = FRequest<T>;
|
|
||||||
type Response = ();
|
|
||||||
type Error = ();
|
|
||||||
type Future = BoxedResponse;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
// let mut ready = true;
|
|
||||||
// for service in &mut self.services {
|
|
||||||
// if let Async::NotReady = service.poll_ready()? {
|
|
||||||
// ready = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ready {
|
|
||||||
// Ok(Async::Ready(()))
|
|
||||||
// } else {
|
|
||||||
// Ok(Async::NotReady)
|
|
||||||
// }
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, (req, framed): (Request, Framed<T, Codec>)) -> Self::Future {
|
|
||||||
let mut path = Path::new(Url::new(req.uri().clone()));
|
|
||||||
|
|
||||||
if let Some((srv, _info)) = self.router.recognize_mut(&mut path) {
|
|
||||||
return srv.call(FramedRequest::new(
|
|
||||||
WebRequest::new(self.state.clone(), req, path),
|
|
||||||
framed,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// for item in &mut self.services {
|
|
||||||
// req = match item.handle(req) {
|
|
||||||
// Ok(fut) => return fut,
|
|
||||||
// Err(req) => req,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// self.default.call(req)
|
|
||||||
Box::new(
|
|
||||||
SendResponse::send(framed, Response::NotFound().finish().into())
|
|
||||||
.map(|_| ())
|
|
||||||
.map_err(|_| ()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,379 +0,0 @@
|
|||||||
use std::marker::PhantomData;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use actix_codec::Framed;
|
|
||||||
use actix_http::{h1::Codec, Error};
|
|
||||||
use actix_service::{NewService, Service};
|
|
||||||
use futures::future::{ok, FutureResult};
|
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
|
||||||
use log::error;
|
|
||||||
|
|
||||||
use crate::handler::FromRequest;
|
|
||||||
use crate::request::Request;
|
|
||||||
|
|
||||||
pub struct FramedError<Io> {
|
|
||||||
pub err: Error,
|
|
||||||
pub framed: Framed<Io, Codec>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedRequest<S, Io, Ex = ()> {
|
|
||||||
req: Request<S>,
|
|
||||||
framed: Framed<Io, Codec>,
|
|
||||||
param: Ex,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Io> FramedRequest<S, Io, ()> {
|
|
||||||
pub fn new(req: Request<S>, framed: Framed<Io, Codec>) -> Self {
|
|
||||||
Self {
|
|
||||||
req,
|
|
||||||
framed,
|
|
||||||
param: (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Io, Ex> FramedRequest<S, Io, Ex> {
|
|
||||||
pub fn request(&self) -> &Request<S> {
|
|
||||||
&self.req
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn request_mut(&mut self) -> &mut Request<S> {
|
|
||||||
&mut self.req
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_parts(self) -> (Request<S>, Framed<Io, Codec>, Ex) {
|
|
||||||
(self.req, self.framed, self.param)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map<Ex2, F>(self, op: F) -> FramedRequest<S, Io, Ex2>
|
|
||||||
where
|
|
||||||
F: FnOnce(Ex) -> Ex2,
|
|
||||||
{
|
|
||||||
FramedRequest {
|
|
||||||
req: self.req,
|
|
||||||
framed: self.framed,
|
|
||||||
param: op(self.param),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// T handler converter factory
|
|
||||||
pub trait FramedFactory<S, Io, Ex, T, R, E>: Clone + 'static
|
|
||||||
where
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
fn call(&self, framed: Framed<Io, Codec>, param: T, extra: Ex) -> R;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct FramedHandle<F, S, Io, Ex, T, R, E>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, Ex, T, R, E>,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
hnd: F,
|
|
||||||
_t: PhantomData<(S, Io, Ex, T, R, E)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, S, Io, Ex, T, R, E> FramedHandle<F, S, Io, Ex, T, R, E>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, Ex, T, R, E>,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
pub fn new(hnd: F) -> Self {
|
|
||||||
FramedHandle {
|
|
||||||
hnd,
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<F, S, Io, Ex, T, R, E> NewService for FramedHandle<F, S, Io, Ex, T, R, E>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, Ex, T, R, E>,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
type Request = (T, FramedRequest<S, Io, Ex>);
|
|
||||||
type Response = ();
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
type InitError = ();
|
|
||||||
type Service = FramedHandleService<F, S, Io, Ex, T, R, E>;
|
|
||||||
type Future = FutureResult<Self::Service, ()>;
|
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
|
||||||
ok(FramedHandleService {
|
|
||||||
hnd: self.hnd.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct FramedHandleService<F, S, Io, Ex, T, R, E>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, Ex, T, R, E>,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
hnd: F,
|
|
||||||
_t: PhantomData<(S, Io, Ex, T, R, E)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, S, Io, Ex, T, R, E> Service for FramedHandleService<F, S, Io, Ex, T, R, E>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, Ex, T, R, E>,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
type Request = (T, FramedRequest<S, Io, Ex>);
|
|
||||||
type Response = ();
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
type Future = FramedHandleServiceResponse<Io, R::Future>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, (param, framed): (T, FramedRequest<S, Io, Ex>)) -> Self::Future {
|
|
||||||
let (_, framed, ex) = framed.into_parts();
|
|
||||||
FramedHandleServiceResponse {
|
|
||||||
fut: self.hnd.call(framed, param, ex).into_future(),
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct FramedHandleServiceResponse<Io, F> {
|
|
||||||
fut: F,
|
|
||||||
_t: PhantomData<Io>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, F> Future for FramedHandleServiceResponse<Io, F>
|
|
||||||
where
|
|
||||||
F: Future<Item = ()>,
|
|
||||||
F::Error: Into<Error>,
|
|
||||||
{
|
|
||||||
type Item = ();
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
match self.fut.poll() {
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
|
||||||
Ok(Async::Ready(res)) => Ok(Async::Ready(res.into())),
|
|
||||||
Err(e) => {
|
|
||||||
let e: Error = e.into();
|
|
||||||
error!("Error in handler: {:?}", e);
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedExtract<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S>,
|
|
||||||
{
|
|
||||||
cfg: Rc<T::Config>,
|
|
||||||
_t: PhantomData<(Io, Ex)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Io, Ex, T> FramedExtract<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S> + 'static,
|
|
||||||
{
|
|
||||||
pub fn new(cfg: T::Config) -> FramedExtract<S, Io, Ex, T> {
|
|
||||||
FramedExtract {
|
|
||||||
cfg: Rc::new(cfg),
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<S, Io, Ex, T> NewService for FramedExtract<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S> + 'static,
|
|
||||||
{
|
|
||||||
type Request = FramedRequest<S, Io, Ex>;
|
|
||||||
type Response = (T, FramedRequest<S, Io, Ex>);
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
type InitError = ();
|
|
||||||
type Service = FramedExtractService<S, Io, Ex, T>;
|
|
||||||
type Future = FutureResult<Self::Service, ()>;
|
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
|
||||||
ok(FramedExtractService {
|
|
||||||
cfg: self.cfg.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedExtractService<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S>,
|
|
||||||
{
|
|
||||||
cfg: Rc<T::Config>,
|
|
||||||
_t: PhantomData<(Io, Ex)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Io, Ex, T> Service for FramedExtractService<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S> + 'static,
|
|
||||||
{
|
|
||||||
type Request = FramedRequest<S, Io, Ex>;
|
|
||||||
type Response = (T, FramedRequest<S, Io, Ex>);
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
type Future = FramedExtractResponse<S, Io, Ex, T>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: FramedRequest<S, Io, Ex>) -> Self::Future {
|
|
||||||
FramedExtractResponse {
|
|
||||||
fut: T::from_request(&req.request(), self.cfg.as_ref()),
|
|
||||||
req: Some(req),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedExtractResponse<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S> + 'static,
|
|
||||||
{
|
|
||||||
req: Option<FramedRequest<S, Io, Ex>>,
|
|
||||||
fut: T::Future,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, Io, Ex, T> Future for FramedExtractResponse<S, Io, Ex, T>
|
|
||||||
where
|
|
||||||
T: FromRequest<S> + 'static,
|
|
||||||
{
|
|
||||||
type Item = (T, FramedRequest<S, Io, Ex>);
|
|
||||||
type Error = FramedError<Io>;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
match self.fut.poll() {
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
|
||||||
Ok(Async::Ready(item)) => Ok(Async::Ready((item, self.req.take().unwrap()))),
|
|
||||||
Err(err) => Err(FramedError {
|
|
||||||
err: err.into(),
|
|
||||||
framed: self.req.take().unwrap().into_parts().1,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! factory_tuple ({ ($(($nex:tt, $Ex:ident)),+), $(($n:tt, $T:ident)),+} => {
|
|
||||||
impl<Func, S, Io, $($Ex,)+ $($T,)+ Res, Err> FramedFactory<S, Io, ($($Ex,)+), ($($T,)+), Res, Err> for Func
|
|
||||||
where Func: Fn(Framed<Io, Codec>, $($Ex,)+ $($T,)+) -> Res + Clone + 'static,
|
|
||||||
$($T: FromRequest<S> + 'static,)+
|
|
||||||
Res: IntoFuture<Item=(), Error=Err> + 'static,
|
|
||||||
Err: Into<Error>,
|
|
||||||
{
|
|
||||||
fn call(&self, framed: Framed<Io, Codec>, param: ($($T,)+), extra: ($($Ex,)+)) -> Res {
|
|
||||||
(self)(framed, $(extra.$nex,)+ $(param.$n,)+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
macro_rules! factory_tuple_unit ({$(($n:tt, $T:ident)),+} => {
|
|
||||||
impl<Func, S, Io, $($T,)+ Res, Err> FramedFactory<S, Io, (), ($($T,)+), Res, Err> for Func
|
|
||||||
where Func: Fn(Framed<Io, Codec>, $($T,)+) -> Res + Clone + 'static,
|
|
||||||
$($T: FromRequest<S> + 'static,)+
|
|
||||||
Res: IntoFuture<Item=(), Error=Err> + 'static,
|
|
||||||
Err: Into<Error>,
|
|
||||||
{
|
|
||||||
fn call(&self, framed: Framed<Io, Codec>, param: ($($T,)+), _extra: () ) -> Res {
|
|
||||||
(self)(framed, $(param.$n,)+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
||||||
mod m {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
|
||||||
|
|
||||||
factory_tuple_unit!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
factory_tuple!(((0, Aex), (1, Bex), (2, Cex), (3, Dex), (4, Eex), (5, Fex)), (0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
|
||||||
}
|
|
@ -1,448 +0,0 @@
|
|||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use actix_http::http::{HeaderName, HeaderValue, Method};
|
|
||||||
use actix_http::Error;
|
|
||||||
use actix_service::{IntoNewService, NewService, NewServiceExt, Service};
|
|
||||||
use futures::{try_ready, Async, Future, IntoFuture, Poll};
|
|
||||||
use log::{debug, error};
|
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
|
||||||
|
|
||||||
use crate::app::{HttpServiceFactory, State};
|
|
||||||
use crate::framed_handler::{
|
|
||||||
FramedError, FramedExtract, FramedFactory, FramedHandle, FramedRequest,
|
|
||||||
};
|
|
||||||
use crate::handler::FromRequest;
|
|
||||||
|
|
||||||
/// Resource route definition
|
|
||||||
///
|
|
||||||
/// Route uses builder-like pattern for configuration.
|
|
||||||
/// If handler is not explicitly set, default *404 Not Found* handler is used.
|
|
||||||
pub struct FramedRoute<Io, T, S = ()> {
|
|
||||||
service: T,
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: PhantomData<(S, Io)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, S> FramedRoute<Io, (), S> {
|
|
||||||
pub fn build(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder::new(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder::new(path).method(Method::GET)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder::new(path).method(Method::POST)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder::new(path).method(Method::PUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder::new(path).method(Method::DELETE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, T, S> FramedRoute<Io, T, S>
|
|
||||||
where
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
> + 'static,
|
|
||||||
{
|
|
||||||
pub fn new<F: IntoNewService<T>>(pattern: &str, factory: F) -> Self {
|
|
||||||
FramedRoute {
|
|
||||||
pattern: pattern.to_string(),
|
|
||||||
service: factory.into_new_service(),
|
|
||||||
headers: Vec::new(),
|
|
||||||
methods: Vec::new(),
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn method(mut self, method: Method) -> Self {
|
|
||||||
self.methods.push(method);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn header(mut self, name: HeaderName, value: HeaderValue) -> Self {
|
|
||||||
self.headers.push((name, value));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, T, S> HttpServiceFactory<S> for FramedRoute<Io, T, S>
|
|
||||||
where
|
|
||||||
Io: AsyncRead + AsyncWrite + 'static,
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
> + 'static,
|
|
||||||
T::Service: 'static,
|
|
||||||
{
|
|
||||||
type Factory = FramedRouteFactory<Io, T, S>;
|
|
||||||
|
|
||||||
fn path(&self) -> &str {
|
|
||||||
&self.pattern
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create(self, state: State<S>) -> Self::Factory {
|
|
||||||
FramedRouteFactory {
|
|
||||||
state,
|
|
||||||
service: self.service,
|
|
||||||
pattern: self.pattern,
|
|
||||||
methods: self.methods,
|
|
||||||
headers: self.headers,
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedRouteFactory<Io, T, S> {
|
|
||||||
service: T,
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: State<S>,
|
|
||||||
_t: PhantomData<Io>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, T, S> NewService for FramedRouteFactory<Io, T, S>
|
|
||||||
where
|
|
||||||
Io: AsyncRead + AsyncWrite + 'static,
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
> + 'static,
|
|
||||||
T::Service: 'static,
|
|
||||||
{
|
|
||||||
type Request = FramedRequest<S, Io>;
|
|
||||||
type Response = T::Response;
|
|
||||||
type Error = ();
|
|
||||||
type InitError = T::InitError;
|
|
||||||
type Service = FramedRouteService<Io, T::Service, S>;
|
|
||||||
type Future = CreateRouteService<Io, T, S>;
|
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
|
||||||
CreateRouteService {
|
|
||||||
fut: self.service.new_service(),
|
|
||||||
pattern: self.pattern.clone(),
|
|
||||||
methods: self.methods.clone(),
|
|
||||||
headers: self.headers.clone(),
|
|
||||||
state: self.state.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CreateRouteService<Io, T: NewService, S> {
|
|
||||||
fut: T::Future,
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: State<S>,
|
|
||||||
_t: PhantomData<Io>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, T, S> Future for CreateRouteService<Io, T, S>
|
|
||||||
where
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
type Item = FramedRouteService<Io, T::Service, S>;
|
|
||||||
type Error = T::InitError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
let service = try_ready!(self.fut.poll());
|
|
||||||
|
|
||||||
Ok(Async::Ready(FramedRouteService {
|
|
||||||
service,
|
|
||||||
state: self.state.clone(),
|
|
||||||
pattern: self.pattern.clone(),
|
|
||||||
methods: self.methods.clone(),
|
|
||||||
headers: self.headers.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedRouteService<Io, T, S> {
|
|
||||||
service: T,
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: State<S>,
|
|
||||||
_t: PhantomData<Io>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, T, S> Service for FramedRouteService<Io, T, S>
|
|
||||||
where
|
|
||||||
Io: AsyncRead + AsyncWrite + 'static,
|
|
||||||
T: Service<Request = FramedRequest<S, Io>, Response = (), Error = FramedError<Io>>
|
|
||||||
+ 'static,
|
|
||||||
{
|
|
||||||
type Request = FramedRequest<S, Io>;
|
|
||||||
type Response = ();
|
|
||||||
type Error = ();
|
|
||||||
type Future = FramedRouteServiceResponse<Io, T::Future>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
self.service.poll_ready().map_err(|e| {
|
|
||||||
debug!("Service not available: {}", e.err);
|
|
||||||
()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: FramedRequest<S, Io>) -> Self::Future {
|
|
||||||
FramedRouteServiceResponse {
|
|
||||||
fut: self.service.call(req),
|
|
||||||
send: None,
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl<Io, T, S> HttpService<(Request, Framed<Io, Codec>)> for FramedRouteService<Io, T, S>
|
|
||||||
// where
|
|
||||||
// Io: AsyncRead + AsyncWrite + 'static,
|
|
||||||
// S: 'static,
|
|
||||||
// T: Service<FramedRequest<S, Io>, Response = (), Error = FramedError<Io>> + 'static,
|
|
||||||
// {
|
|
||||||
// fn handle(
|
|
||||||
// &mut self,
|
|
||||||
// (req, framed): (Request, Framed<Io, Codec>),
|
|
||||||
// ) -> Result<Self::Future, (Request, Framed<Io, Codec>)> {
|
|
||||||
// if self.methods.is_empty()
|
|
||||||
// || !self.methods.is_empty() && self.methods.contains(req.method())
|
|
||||||
// {
|
|
||||||
// if let Some(params) = self.pattern.match_with_params(&req, 0) {
|
|
||||||
// return Ok(FramedRouteServiceResponse {
|
|
||||||
// fut: self.service.call(FramedRequest::new(
|
|
||||||
// WebRequest::new(self.state.clone(), req, params),
|
|
||||||
// framed,
|
|
||||||
// )),
|
|
||||||
// send: None,
|
|
||||||
// _t: PhantomData,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Err((req, framed))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct FramedRouteServiceResponse<Io, F> {
|
|
||||||
fut: F,
|
|
||||||
send: Option<Box<Future<Item = (), Error = Error>>>,
|
|
||||||
_t: PhantomData<Io>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, F> Future for FramedRouteServiceResponse<Io, F>
|
|
||||||
where
|
|
||||||
F: Future<Error = FramedError<Io>>,
|
|
||||||
Io: AsyncRead + AsyncWrite + 'static,
|
|
||||||
{
|
|
||||||
type Item = ();
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
if let Some(ref mut fut) = self.send {
|
|
||||||
return match fut.poll() {
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
|
||||||
Ok(Async::Ready(_)) => Ok(Async::Ready(())),
|
|
||||||
Err(e) => {
|
|
||||||
debug!("Error during error response send: {}", e);
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.fut.poll() {
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
|
||||||
Ok(Async::Ready(_)) => Ok(Async::Ready(())),
|
|
||||||
Err(e) => {
|
|
||||||
error!("Error occurred during request handling: {}", e.err);
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedRoutePatternBuilder<Io, S> {
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: PhantomData<(Io, S)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, S> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
fn new(path: &str) -> FramedRoutePatternBuilder<Io, S> {
|
|
||||||
FramedRoutePatternBuilder {
|
|
||||||
pattern: path.to_string(),
|
|
||||||
methods: Vec::new(),
|
|
||||||
headers: Vec::new(),
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn method(mut self, method: Method) -> Self {
|
|
||||||
self.methods.push(method);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map<T, U, F: IntoNewService<T>>(
|
|
||||||
self,
|
|
||||||
md: F,
|
|
||||||
) -> FramedRouteBuilder<Io, S, T, (), U>
|
|
||||||
where
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = FramedRequest<S, Io, U>,
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
FramedRouteBuilder {
|
|
||||||
service: md.into_new_service(),
|
|
||||||
pattern: self.pattern,
|
|
||||||
methods: self.methods,
|
|
||||||
headers: self.headers,
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with<F, P, R, E>(
|
|
||||||
self,
|
|
||||||
handler: F,
|
|
||||||
) -> FramedRoute<
|
|
||||||
Io,
|
|
||||||
impl NewService<
|
|
||||||
Request = FramedRequest<S, Io>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
S,
|
|
||||||
>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, (), P, R, E>,
|
|
||||||
P: FromRequest<S> + 'static,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
FramedRoute {
|
|
||||||
service: FramedExtract::new(P::Config::default())
|
|
||||||
.and_then(FramedHandle::new(handler)),
|
|
||||||
pattern: self.pattern,
|
|
||||||
methods: self.methods,
|
|
||||||
headers: self.headers,
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FramedRouteBuilder<Io, S, T, U1, U2> {
|
|
||||||
service: T,
|
|
||||||
pattern: String,
|
|
||||||
methods: Vec<Method>,
|
|
||||||
headers: Vec<(HeaderName, HeaderValue)>,
|
|
||||||
state: PhantomData<(Io, S, U1, U2)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io, S, T, U1, U2> FramedRouteBuilder<Io, S, T, U1, U2>
|
|
||||||
where
|
|
||||||
T: NewService<
|
|
||||||
Request = FramedRequest<S, Io, U1>,
|
|
||||||
Response = FramedRequest<S, Io, U2>,
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
pub fn new<F: IntoNewService<T>>(path: &str, factory: F) -> Self {
|
|
||||||
FramedRouteBuilder {
|
|
||||||
service: factory.into_new_service(),
|
|
||||||
pattern: path.to_string(),
|
|
||||||
methods: Vec::new(),
|
|
||||||
headers: Vec::new(),
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn method(mut self, method: Method) -> Self {
|
|
||||||
self.methods.push(method);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map<K, U3, F: IntoNewService<K>>(
|
|
||||||
self,
|
|
||||||
md: F,
|
|
||||||
) -> FramedRouteBuilder<
|
|
||||||
Io,
|
|
||||||
S,
|
|
||||||
impl NewService<
|
|
||||||
Request = FramedRequest<S, Io, U1>,
|
|
||||||
Response = FramedRequest<S, Io, U3>,
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
U1,
|
|
||||||
U3,
|
|
||||||
>
|
|
||||||
where
|
|
||||||
K: NewService<
|
|
||||||
Request = FramedRequest<S, Io, U2>,
|
|
||||||
Response = FramedRequest<S, Io, U3>,
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
FramedRouteBuilder {
|
|
||||||
service: self.service.from_err().and_then(md.into_new_service()),
|
|
||||||
pattern: self.pattern,
|
|
||||||
methods: self.methods,
|
|
||||||
headers: self.headers,
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with<F, P, R, E>(
|
|
||||||
self,
|
|
||||||
handler: F,
|
|
||||||
) -> FramedRoute<
|
|
||||||
Io,
|
|
||||||
impl NewService<
|
|
||||||
Request = FramedRequest<S, Io, U1>,
|
|
||||||
Response = (),
|
|
||||||
Error = FramedError<Io>,
|
|
||||||
InitError = (),
|
|
||||||
>,
|
|
||||||
S,
|
|
||||||
>
|
|
||||||
where
|
|
||||||
F: FramedFactory<S, Io, U2, P, R, E>,
|
|
||||||
P: FromRequest<S> + 'static,
|
|
||||||
R: IntoFuture<Item = (), Error = E>,
|
|
||||||
E: Into<Error>,
|
|
||||||
{
|
|
||||||
FramedRoute {
|
|
||||||
service: self
|
|
||||||
.service
|
|
||||||
.and_then(FramedExtract::new(P::Config::default()))
|
|
||||||
.and_then(FramedHandle::new(handler)),
|
|
||||||
pattern: self.pattern,
|
|
||||||
methods: self.methods,
|
|
||||||
headers: self.headers,
|
|
||||||
state: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
180
src/helpers.rs
180
src/helpers.rs
@ -1,180 +0,0 @@
|
|||||||
use actix_http::Response;
|
|
||||||
use actix_service::{NewService, Service};
|
|
||||||
use futures::future::{ok, FutureResult};
|
|
||||||
use futures::{Future, Poll};
|
|
||||||
|
|
||||||
pub(crate) type BoxedHttpService<Req, Res> = Box<
|
|
||||||
Service<
|
|
||||||
Request = Req,
|
|
||||||
Response = Res,
|
|
||||||
Error = (),
|
|
||||||
Future = Box<Future<Item = Res, Error = ()>>,
|
|
||||||
>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub(crate) type BoxedHttpNewService<Req, Res> = Box<
|
|
||||||
NewService<
|
|
||||||
Request = Req,
|
|
||||||
Response = Res,
|
|
||||||
Error = (),
|
|
||||||
InitError = (),
|
|
||||||
Service = BoxedHttpService<Req, Res>,
|
|
||||||
Future = Box<Future<Item = BoxedHttpService<Req, Res>, Error = ()>>,
|
|
||||||
>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub(crate) struct HttpNewService<T: NewService>(T);
|
|
||||||
|
|
||||||
impl<T> HttpNewService<T>
|
|
||||||
where
|
|
||||||
T: NewService,
|
|
||||||
T::Response: 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
T::Service: Service,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
pub fn new(service: T) -> Self {
|
|
||||||
HttpNewService(service)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> NewService for HttpNewService<T>
|
|
||||||
where
|
|
||||||
T: NewService,
|
|
||||||
T::Request: 'static,
|
|
||||||
T::Response: 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
T::Service: Service + 'static,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
type Request = T::Request;
|
|
||||||
type Response = T::Response;
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = BoxedHttpService<T::Request, T::Response>;
|
|
||||||
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
|
|
||||||
|
|
||||||
fn new_service(&self, _: &()) -> Self::Future {
|
|
||||||
Box::new(self.0.new_service(&()).map_err(|_| ()).and_then(|service| {
|
|
||||||
let service: BoxedHttpService<_, _> =
|
|
||||||
Box::new(HttpServiceWrapper { service });
|
|
||||||
Ok(service)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HttpServiceWrapper<T: Service> {
|
|
||||||
service: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Service for HttpServiceWrapper<T>
|
|
||||||
where
|
|
||||||
T: Service,
|
|
||||||
T::Request: 'static,
|
|
||||||
T::Response: 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
{
|
|
||||||
type Request = T::Request;
|
|
||||||
type Response = T::Response;
|
|
||||||
type Error = ();
|
|
||||||
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
self.service.poll_ready().map_err(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
|
||||||
Box::new(self.service.call(req).map_err(|_| ()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn not_found<Req>(_: Req) -> FutureResult<Response, ()> {
|
|
||||||
ok(Response::NotFound().finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) type HttpDefaultService<Req, Res> = Box<
|
|
||||||
Service<
|
|
||||||
Request = Req,
|
|
||||||
Response = Res,
|
|
||||||
Error = (),
|
|
||||||
Future = Box<Future<Item = Res, Error = ()>>,
|
|
||||||
>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub(crate) type HttpDefaultNewService<Req, Res> = Box<
|
|
||||||
NewService<
|
|
||||||
Request = Req,
|
|
||||||
Response = Res,
|
|
||||||
Error = (),
|
|
||||||
InitError = (),
|
|
||||||
Service = HttpDefaultService<Req, Res>,
|
|
||||||
Future = Box<Future<Item = HttpDefaultService<Req, Res>, Error = ()>>,
|
|
||||||
>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub(crate) struct DefaultNewService<T: NewService> {
|
|
||||||
service: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DefaultNewService<T>
|
|
||||||
where
|
|
||||||
T: NewService + 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
pub fn new(service: T) -> Self {
|
|
||||||
DefaultNewService { service }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> NewService for DefaultNewService<T>
|
|
||||||
where
|
|
||||||
T: NewService + 'static,
|
|
||||||
T::Request: 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
T::Service: 'static,
|
|
||||||
<T::Service as Service>::Future: 'static,
|
|
||||||
{
|
|
||||||
type Request = T::Request;
|
|
||||||
type Response = T::Response;
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = HttpDefaultService<T::Request, T::Response>;
|
|
||||||
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
|
|
||||||
|
|
||||||
fn new_service(&self, _: &()) -> Self::Future {
|
|
||||||
Box::new(
|
|
||||||
self.service
|
|
||||||
.new_service(&())
|
|
||||||
.map_err(|_| ())
|
|
||||||
.and_then(|service| {
|
|
||||||
let service: HttpDefaultService<_, _> =
|
|
||||||
Box::new(DefaultServiceWrapper { service });
|
|
||||||
Ok(service)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DefaultServiceWrapper<T: Service> {
|
|
||||||
service: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Service for DefaultServiceWrapper<T>
|
|
||||||
where
|
|
||||||
T: Service + 'static,
|
|
||||||
T::Future: 'static,
|
|
||||||
{
|
|
||||||
type Request = T::Request;
|
|
||||||
type Response = T::Response;
|
|
||||||
type Error = ();
|
|
||||||
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
self.service.poll_ready().map_err(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: T::Request) -> Self::Future {
|
|
||||||
Box::new(self.service.call(req).map_err(|_| ()))
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,11 +3,10 @@
|
|||||||
mod app;
|
mod app;
|
||||||
mod extractor;
|
mod extractor;
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
mod helpers;
|
// mod helpers;
|
||||||
// mod info;
|
// mod info;
|
||||||
pub mod blocking;
|
pub mod blocking;
|
||||||
pub mod filter;
|
pub mod filter;
|
||||||
pub mod fs;
|
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
mod request;
|
mod request;
|
||||||
mod resource;
|
mod resource;
|
||||||
|
@ -2,6 +2,7 @@ use std::cell::RefCell;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use actix_http::{http::Method, Error, Response};
|
use actix_http::{http::Method, Error, Response};
|
||||||
|
use actix_service::boxed::{self, BoxedNewService, BoxedService};
|
||||||
use actix_service::{
|
use actix_service::{
|
||||||
ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service,
|
ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service,
|
||||||
};
|
};
|
||||||
@ -9,11 +10,13 @@ use futures::future::{ok, Either, FutureResult};
|
|||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::handler::{AsyncFactory, Factory, FromRequest};
|
use crate::handler::{AsyncFactory, Factory, FromRequest};
|
||||||
use crate::helpers::{DefaultNewService, HttpDefaultNewService, HttpDefaultService};
|
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::route::{CreateRouteService, Route, RouteBuilder, RouteService};
|
use crate::route::{CreateRouteService, Route, RouteBuilder, RouteService};
|
||||||
use crate::service::{ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceRequest, ServiceResponse};
|
||||||
|
|
||||||
|
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
|
||||||
|
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||||
|
|
||||||
/// Resource route definition
|
/// Resource route definition
|
||||||
///
|
///
|
||||||
/// Route uses builder-like pattern for configuration.
|
/// Route uses builder-like pattern for configuration.
|
||||||
@ -21,9 +24,7 @@ use crate::service::{ServiceRequest, ServiceResponse};
|
|||||||
pub struct Resource<P, T = ResourceEndpoint<P>> {
|
pub struct Resource<P, T = ResourceEndpoint<P>> {
|
||||||
routes: Vec<Route<P>>,
|
routes: Vec<Route<P>>,
|
||||||
endpoint: T,
|
endpoint: T,
|
||||||
default: Rc<
|
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
|
||||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>,
|
|
||||||
>,
|
|
||||||
factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
|
factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,17 +278,14 @@ where
|
|||||||
> + 'static,
|
> + 'static,
|
||||||
{
|
{
|
||||||
// create and configure default resource
|
// create and configure default resource
|
||||||
self.default = Rc::new(RefCell::new(Some(Rc::new(Box::new(
|
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
|
||||||
DefaultNewService::new(f(Resource::new()).into_new_service()),
|
f(Resource::new()).into_new_service().map_init_err(|_| ()),
|
||||||
)))));
|
)))));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_default(
|
pub(crate) fn get_default(&self) -> Rc<RefCell<Option<Rc<HttpNewService<P>>>>> {
|
||||||
&self,
|
|
||||||
) -> Rc<RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>>
|
|
||||||
{
|
|
||||||
self.default.clone()
|
self.default.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,12 +311,10 @@ where
|
|||||||
|
|
||||||
pub struct ResourceFactory<P> {
|
pub struct ResourceFactory<P> {
|
||||||
routes: Vec<Route<P>>,
|
routes: Vec<Route<P>>,
|
||||||
default: Rc<
|
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
|
||||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> NewService for ResourceFactory<P> {
|
impl<P: 'static> NewService for ResourceFactory<P> {
|
||||||
type Request = ServiceRequest<P>;
|
type Request = ServiceRequest<P>;
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
@ -352,15 +348,8 @@ enum CreateRouteServiceItem<P> {
|
|||||||
|
|
||||||
pub struct CreateResourceService<P> {
|
pub struct CreateResourceService<P> {
|
||||||
fut: Vec<CreateRouteServiceItem<P>>,
|
fut: Vec<CreateRouteServiceItem<P>>,
|
||||||
default: Option<HttpDefaultService<ServiceRequest<P>, ServiceResponse>>,
|
default: Option<HttpService<P>>,
|
||||||
default_fut: Option<
|
default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
|
||||||
Box<
|
|
||||||
Future<
|
|
||||||
Item = HttpDefaultService<ServiceRequest<P>, ServiceResponse>,
|
|
||||||
Error = (),
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> Future for CreateResourceService<P> {
|
impl<P> Future for CreateResourceService<P> {
|
||||||
@ -413,7 +402,7 @@ impl<P> Future for CreateResourceService<P> {
|
|||||||
|
|
||||||
pub struct ResourceService<P> {
|
pub struct ResourceService<P> {
|
||||||
routes: Vec<RouteService<P>>,
|
routes: Vec<RouteService<P>>,
|
||||||
default: Option<HttpDefaultService<ServiceRequest<P>, ServiceResponse>>,
|
default: Option<HttpService<P>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> Service for ResourceService<P> {
|
impl<P> Service for ResourceService<P> {
|
||||||
@ -461,7 +450,7 @@ impl<P> ResourceEndpoint<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> NewService for ResourceEndpoint<P> {
|
impl<P: 'static> NewService for ResourceEndpoint<P> {
|
||||||
type Request = ServiceRequest<P>;
|
type Request = ServiceRequest<P>;
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
@ -12,7 +12,7 @@ use flate2::write::ZlibDecoder;
|
|||||||
use futures::stream::once; //Future, Stream
|
use futures::stream::once; //Future, Stream
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
|
|
||||||
use actix_web2::{middleware, App};
|
use actix_web::{middleware, App};
|
||||||
|
|
||||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
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 \
|
||||||
|
Loading…
Reference in New Issue
Block a user