mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +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"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
".",
|
||||
"actix-web-fs",
|
||||
]
|
||||
|
||||
[features]
|
||||
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::{HttpMessage, Response};
|
||||
use actix_service::boxed::BoxedNewService;
|
||||
use actix_service::{NewService, Service};
|
||||
use actix_web::{
|
||||
blocking, FromRequest, HttpRequest, Responder, ServiceRequest, ServiceResponse,
|
||||
};
|
||||
use futures::future::{err, ok, FutureResult};
|
||||
|
||||
use crate::blocking;
|
||||
use crate::handler::FromRequest;
|
||||
use crate::helpers::HttpDefaultNewService;
|
||||
use crate::request::HttpRequest;
|
||||
use crate::responder::Responder;
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||
|
||||
///Describes `StaticFiles` configiration
|
||||
///
|
||||
@ -101,6 +100,7 @@ pub trait StaticFileConfig: Default {
|
||||
///[StaticFileConfig](trait.StaticFileConfig.html)
|
||||
#[derive(Default)]
|
||||
pub struct DefaultConfig;
|
||||
|
||||
impl StaticFileConfig for DefaultConfig {}
|
||||
|
||||
/// Return the MIME type associated with a filename extension (case-insensitive).
|
||||
@ -716,9 +716,7 @@ pub struct StaticFiles<S, C = DefaultConfig> {
|
||||
directory: PathBuf,
|
||||
index: Option<String>,
|
||||
show_index: bool,
|
||||
default: Rc<
|
||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<S>, ServiceResponse>>>>,
|
||||
>,
|
||||
default: Rc<RefCell<Option<Rc<HttpNewService<S>>>>>,
|
||||
renderer: Rc<DirectoryRenderer>,
|
||||
_chunk_size: usize,
|
||||
_follow_symlinks: bool,
|
||||
@ -817,9 +815,7 @@ pub struct StaticFilesService<S, C = DefaultConfig> {
|
||||
directory: PathBuf,
|
||||
index: Option<String>,
|
||||
show_index: bool,
|
||||
default: Rc<
|
||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<S>, ServiceResponse>>>>,
|
||||
>,
|
||||
default: Rc<RefCell<Option<Rc<HttpNewService<S>>>>>,
|
||||
renderer: Rc<DirectoryRenderer>,
|
||||
_chunk_size: usize,
|
||||
_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 {
|
||||
let mut req = req;
|
||||
let real_path = match PathBuf::from_request(&mut req).poll() {
|
||||
Ok(Async::Ready(item)) => item,
|
||||
let real_path = match PathBufWrp::from_request(&mut req).poll() {
|
||||
Ok(Async::Ready(item)) => item.0,
|
||||
Ok(Async::NotReady) => unreachable!(),
|
||||
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 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_server::Server;
|
||||
use actix_web2::{middleware, App, Error, HttpRequest, Resource};
|
||||
use actix_web::{middleware, App, Error, HttpRequest, Resource};
|
||||
|
||||
fn index(req: HttpRequest) -> &'static str {
|
||||
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::{Extensions, PayloadStream, Request, Response};
|
||||
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
|
||||
use actix_service::boxed::{self, BoxedNewService, BoxedService};
|
||||
use actix_service::{
|
||||
AndThenNewService, ApplyNewService, IntoNewService, IntoNewTransform, NewService,
|
||||
NewTransform, Service,
|
||||
@ -12,13 +13,12 @@ use actix_service::{
|
||||
use futures::future::{ok, Either, FutureResult};
|
||||
use futures::{Async, Future, IntoFuture, Poll};
|
||||
|
||||
use crate::helpers::{
|
||||
BoxedHttpNewService, BoxedHttpService, DefaultNewService, HttpDefaultNewService,
|
||||
};
|
||||
use crate::resource::Resource;
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
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 = ()>>;
|
||||
|
||||
pub trait HttpServiceFactory<Request> {
|
||||
@ -31,18 +31,9 @@ pub trait HttpServiceFactory<Request> {
|
||||
|
||||
/// Application builder
|
||||
pub struct App<P, B, T> {
|
||||
services: Vec<(
|
||||
ResourceDef,
|
||||
BoxedHttpNewService<ServiceRequest<P>, ServiceResponse>,
|
||||
)>,
|
||||
default: Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>,
|
||||
defaults: Vec<
|
||||
Rc<
|
||||
RefCell<
|
||||
Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
services: Vec<(ResourceDef, HttpNewService<P>)>,
|
||||
default: Option<Rc<HttpNewService<P>>>,
|
||||
defaults: Vec<Rc<RefCell<Option<Rc<HttpNewService<P>>>>>>,
|
||||
endpoint: T,
|
||||
factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
||||
extensions: Extensions,
|
||||
@ -181,10 +172,8 @@ where
|
||||
let rdef = ResourceDef::new(path);
|
||||
let resource = f(Resource::new());
|
||||
self.defaults.push(resource.get_default());
|
||||
self.services.push((
|
||||
rdef,
|
||||
Box::new(HttpNewService::new(resource.into_new_service())),
|
||||
));
|
||||
self.services
|
||||
.push((rdef, boxed::new_service(resource.into_new_service())));
|
||||
self
|
||||
}
|
||||
|
||||
@ -203,9 +192,9 @@ where
|
||||
> + 'static,
|
||||
{
|
||||
// create and configure default resource
|
||||
self.default = Some(Rc::new(Box::new(DefaultNewService::new(
|
||||
f(Resource::new()).into_new_service(),
|
||||
))));
|
||||
self.default = Some(Rc::new(boxed::new_service(
|
||||
f(Resource::new()).into_new_service().map_init_err(|_| ()),
|
||||
)));
|
||||
|
||||
self
|
||||
}
|
||||
@ -223,7 +212,7 @@ where
|
||||
{
|
||||
self.services.push((
|
||||
rdef.into(),
|
||||
Box::new(HttpNewService::new(factory.into_new_service())),
|
||||
boxed::new_service(factory.into_new_service().map_init_err(|_| ())),
|
||||
));
|
||||
self
|
||||
}
|
||||
@ -422,15 +411,10 @@ impl<P> Service for AppStateService<P> {
|
||||
}
|
||||
|
||||
pub struct AppFactory<P> {
|
||||
services: Rc<
|
||||
Vec<(
|
||||
ResourceDef,
|
||||
BoxedHttpNewService<ServiceRequest<P>, ServiceResponse>,
|
||||
)>,
|
||||
>,
|
||||
services: Rc<Vec<(ResourceDef, HttpNewService<P>)>>,
|
||||
}
|
||||
|
||||
impl<P> NewService for AppFactory<P> {
|
||||
impl<P: 'static> NewService for AppFactory<P> {
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = ServiceResponse;
|
||||
type Error = ();
|
||||
@ -454,8 +438,7 @@ impl<P> NewService for AppFactory<P> {
|
||||
}
|
||||
}
|
||||
|
||||
type HttpServiceFut<P> =
|
||||
Box<Future<Item = BoxedHttpService<ServiceRequest<P>, ServiceResponse>, Error = ()>>;
|
||||
type HttpServiceFut<P> = Box<Future<Item = HttpService<P>, Error = ()>>;
|
||||
|
||||
/// Create app service
|
||||
#[doc(hidden)]
|
||||
@ -465,10 +448,7 @@ pub struct CreateAppService<P> {
|
||||
|
||||
enum CreateAppServiceItem<P> {
|
||||
Future(Option<ResourceDef>, HttpServiceFut<P>),
|
||||
Service(
|
||||
ResourceDef,
|
||||
BoxedHttpService<ServiceRequest<P>, ServiceResponse>,
|
||||
),
|
||||
Service(ResourceDef, HttpService<P>),
|
||||
}
|
||||
|
||||
impl<P> Future for CreateAppService<P> {
|
||||
@ -522,7 +502,7 @@ impl<P> Future for CreateAppService<P> {
|
||||
}
|
||||
|
||||
pub struct AppService<P> {
|
||||
router: Router<BoxedHttpService<ServiceRequest<P>, ServiceResponse>>,
|
||||
router: Router<HttpService<P>>,
|
||||
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)]
|
||||
pub struct AppEntry<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 Response = ServiceResponse;
|
||||
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 extractor;
|
||||
pub mod handler;
|
||||
mod helpers;
|
||||
// mod helpers;
|
||||
// mod info;
|
||||
pub mod blocking;
|
||||
pub mod filter;
|
||||
pub mod fs;
|
||||
pub mod middleware;
|
||||
mod request;
|
||||
mod resource;
|
||||
|
@ -2,6 +2,7 @@ use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use actix_http::{http::Method, Error, Response};
|
||||
use actix_service::boxed::{self, BoxedNewService, BoxedService};
|
||||
use actix_service::{
|
||||
ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service,
|
||||
};
|
||||
@ -9,11 +10,13 @@ use futures::future::{ok, Either, FutureResult};
|
||||
use futures::{Async, Future, IntoFuture, Poll};
|
||||
|
||||
use crate::handler::{AsyncFactory, Factory, FromRequest};
|
||||
use crate::helpers::{DefaultNewService, HttpDefaultNewService, HttpDefaultService};
|
||||
use crate::responder::Responder;
|
||||
use crate::route::{CreateRouteService, Route, RouteBuilder, RouteService};
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
|
||||
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
|
||||
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||
|
||||
/// Resource route definition
|
||||
///
|
||||
/// Route uses builder-like pattern for configuration.
|
||||
@ -21,9 +24,7 @@ use crate::service::{ServiceRequest, ServiceResponse};
|
||||
pub struct Resource<P, T = ResourceEndpoint<P>> {
|
||||
routes: Vec<Route<P>>,
|
||||
endpoint: T,
|
||||
default: Rc<
|
||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>,
|
||||
>,
|
||||
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
|
||||
factory_ref: Rc<RefCell<Option<ResourceFactory<P>>>>,
|
||||
}
|
||||
|
||||
@ -277,17 +278,14 @@ where
|
||||
> + 'static,
|
||||
{
|
||||
// create and configure default resource
|
||||
self.default = Rc::new(RefCell::new(Some(Rc::new(Box::new(
|
||||
DefaultNewService::new(f(Resource::new()).into_new_service()),
|
||||
self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::new_service(
|
||||
f(Resource::new()).into_new_service().map_init_err(|_| ()),
|
||||
)))));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn get_default(
|
||||
&self,
|
||||
) -> Rc<RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>>
|
||||
{
|
||||
pub(crate) fn get_default(&self) -> Rc<RefCell<Option<Rc<HttpNewService<P>>>>> {
|
||||
self.default.clone()
|
||||
}
|
||||
}
|
||||
@ -313,12 +311,10 @@ where
|
||||
|
||||
pub struct ResourceFactory<P> {
|
||||
routes: Vec<Route<P>>,
|
||||
default: Rc<
|
||||
RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, ServiceResponse>>>>,
|
||||
>,
|
||||
default: Rc<RefCell<Option<Rc<HttpNewService<P>>>>>,
|
||||
}
|
||||
|
||||
impl<P> NewService for ResourceFactory<P> {
|
||||
impl<P: 'static> NewService for ResourceFactory<P> {
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = ServiceResponse;
|
||||
type Error = ();
|
||||
@ -352,15 +348,8 @@ enum CreateRouteServiceItem<P> {
|
||||
|
||||
pub struct CreateResourceService<P> {
|
||||
fut: Vec<CreateRouteServiceItem<P>>,
|
||||
default: Option<HttpDefaultService<ServiceRequest<P>, ServiceResponse>>,
|
||||
default_fut: Option<
|
||||
Box<
|
||||
Future<
|
||||
Item = HttpDefaultService<ServiceRequest<P>, ServiceResponse>,
|
||||
Error = (),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
default: Option<HttpService<P>>,
|
||||
default_fut: Option<Box<Future<Item = HttpService<P>, Error = ()>>>,
|
||||
}
|
||||
|
||||
impl<P> Future for CreateResourceService<P> {
|
||||
@ -413,7 +402,7 @@ impl<P> Future for CreateResourceService<P> {
|
||||
|
||||
pub struct ResourceService<P> {
|
||||
routes: Vec<RouteService<P>>,
|
||||
default: Option<HttpDefaultService<ServiceRequest<P>, ServiceResponse>>,
|
||||
default: Option<HttpService<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 Response = ServiceResponse;
|
||||
type Error = ();
|
||||
|
@ -12,7 +12,7 @@ use flate2::write::ZlibDecoder;
|
||||
use futures::stream::once; //Future, Stream
|
||||
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 \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
|
Loading…
Reference in New Issue
Block a user