1
0
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:
Nikolay Kim 2019-03-01 23:59:44 -08:00
parent 2d7293aaf8
commit e6d04d24cc
15 changed files with 184 additions and 1406 deletions

View File

@ -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"]

View File

@ -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
View File

@ -0,0 +1,5 @@
# Changes
## [0.1.0] - 2018-10-x
* Initial impl

42
actix-web-fs/Cargo.toml Normal file
View 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
View 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.

View File

@ -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))
} }
} }

View File

@ -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);

View File

@ -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 = ();

View File

@ -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(|_| ()),
)
}
}

View File

@ -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));
}

View File

@ -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,
}
}
}

View File

@ -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(|_| ()))
}
}

View File

@ -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;

View File

@ -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 = ();

View File

@ -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 \