mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-28 01:52:57 +01:00
add request chain services
This commit is contained in:
parent
fdf3011837
commit
cc20fee628
480
src/app.rs
480
src/app.rs
@ -2,7 +2,7 @@ use std::cell::RefCell;
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use actix_http::body::{Body, MessageBody};
|
use actix_http::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::boxed::{self, BoxedNewService, BoxedService};
|
||||||
@ -30,32 +30,45 @@ pub trait HttpServiceFactory<Request> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Application builder
|
/// Application builder
|
||||||
pub struct App<P, B, T> {
|
pub struct App<P, T>
|
||||||
services: Vec<(ResourceDef, HttpNewService<P>)>,
|
where
|
||||||
default: Option<Rc<HttpNewService<P>>>,
|
T: NewService<Request = ServiceRequest<PayloadStream>, Response = ServiceRequest<P>>,
|
||||||
defaults: Vec<Rc<RefCell<Option<Rc<HttpNewService<P>>>>>>,
|
{
|
||||||
endpoint: T,
|
chain: T,
|
||||||
factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
|
||||||
extensions: Extensions,
|
extensions: Extensions,
|
||||||
state: Vec<Box<StateFactory>>,
|
state: Vec<Box<StateFactory>>,
|
||||||
_t: PhantomData<(P, B)>,
|
_t: PhantomData<(P,)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App<PayloadStream, Body, AppEntry<PayloadStream>> {
|
impl App<PayloadStream, AppChain> {
|
||||||
/// Create application with empty state. Application can
|
/// Create application builder with empty state. Application can
|
||||||
/// be configured with a builder-like pattern.
|
/// be configured with a builder-like pattern.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
App::create()
|
App {
|
||||||
|
chain: AppChain,
|
||||||
|
extensions: Extensions::new(),
|
||||||
|
state: Vec::new(),
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for App<PayloadStream, Body, AppEntry<PayloadStream>> {
|
impl Default for App<PayloadStream, AppChain> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
App::new()
|
App::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App<PayloadStream, Body, AppEntry<PayloadStream>> {
|
impl<P, T> App<P, T>
|
||||||
|
where
|
||||||
|
P: 'static,
|
||||||
|
T: NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
{
|
||||||
/// Create application with specified state. Application can be
|
/// Create application with specified state. Application can be
|
||||||
/// configured with a builder-like pattern.
|
/// configured with a builder-like pattern.
|
||||||
///
|
///
|
||||||
@ -86,38 +99,172 @@ impl App<PayloadStream, Body, AppEntry<PayloadStream>> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create() -> Self {
|
/// Configure resource for a specific path.
|
||||||
|
///
|
||||||
|
/// Resources may have variable path segments. For example, a
|
||||||
|
/// resource with the path `/a/{name}/c` would match all incoming
|
||||||
|
/// requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
|
||||||
|
///
|
||||||
|
/// A variable segment is specified in the form `{identifier}`,
|
||||||
|
/// where the identifier can be used later in a request handler to
|
||||||
|
/// access the matched value for that segment. This is done by
|
||||||
|
/// looking up the identifier in the `Params` object returned by
|
||||||
|
/// `HttpRequest.match_info()` method.
|
||||||
|
///
|
||||||
|
/// By default, each segment matches the regular expression `[^{}/]+`.
|
||||||
|
///
|
||||||
|
/// You can also specify a custom regex in the form `{identifier:regex}`:
|
||||||
|
///
|
||||||
|
/// For instance, to route `GET`-requests on any route matching
|
||||||
|
/// `/users/{userid}/{friend}` and store `userid` and `friend` in
|
||||||
|
/// the exposed `Params` object:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// use actix_web::{http, App, HttpResponse};
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let app = App::new().resource("/users/{userid}/{friend}", |r| {
|
||||||
|
/// r.get(|r| r.to(|_| HttpResponse::Ok()));
|
||||||
|
/// r.head(|r| r.to(|_| HttpResponse::MethodNotAllowed()))
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn resource<F, U, B>(self, path: &str, f: F) -> AppRouter<T, P, B, AppEntry<P>>
|
||||||
|
where
|
||||||
|
F: FnOnce(Resource<P>) -> Resource<P, U>,
|
||||||
|
U: NewService<
|
||||||
|
Request = ServiceRequest<P>,
|
||||||
|
Response = ServiceResponse,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
> + 'static,
|
||||||
|
{
|
||||||
|
let rdef = ResourceDef::new(path);
|
||||||
|
let resource = f(Resource::new());
|
||||||
|
let default = resource.get_default();
|
||||||
|
|
||||||
let fref = Rc::new(RefCell::new(None));
|
let fref = Rc::new(RefCell::new(None));
|
||||||
|
AppRouter {
|
||||||
|
chain: self.chain,
|
||||||
|
services: vec![(rdef, boxed::new_service(resource.into_new_service()))],
|
||||||
|
default: None,
|
||||||
|
defaults: vec![default],
|
||||||
|
endpoint: AppEntry::new(fref.clone()),
|
||||||
|
factory_ref: fref,
|
||||||
|
extensions: self.extensions,
|
||||||
|
state: self.state,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register a middleware.
|
||||||
|
pub fn middleware<M, B, F>(
|
||||||
|
self,
|
||||||
|
mw: F,
|
||||||
|
) -> AppRouter<
|
||||||
|
T,
|
||||||
|
P,
|
||||||
|
B,
|
||||||
|
impl NewService<
|
||||||
|
Request = ServiceRequest<P>,
|
||||||
|
Response = ServiceResponse<B>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
M: NewTransform<
|
||||||
|
AppService<P>,
|
||||||
|
Request = ServiceRequest<P>,
|
||||||
|
Response = ServiceResponse<B>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
B: MessageBody,
|
||||||
|
F: IntoNewTransform<M, AppService<P>>,
|
||||||
|
{
|
||||||
|
let fref = Rc::new(RefCell::new(None));
|
||||||
|
let endpoint = ApplyNewService::new(mw, AppEntry::new(fref.clone()));
|
||||||
|
AppRouter {
|
||||||
|
endpoint,
|
||||||
|
chain: self.chain,
|
||||||
|
state: self.state,
|
||||||
|
services: Vec::new(),
|
||||||
|
default: None,
|
||||||
|
defaults: Vec::new(),
|
||||||
|
factory_ref: fref,
|
||||||
|
extensions: self.extensions,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register a request modifier. It can modify any request parameters
|
||||||
|
/// including payload stream.
|
||||||
|
pub fn chain<C, F, P1>(
|
||||||
|
self,
|
||||||
|
chain: C,
|
||||||
|
) -> App<
|
||||||
|
P1,
|
||||||
|
impl NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P1>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
C: NewService<
|
||||||
|
(),
|
||||||
|
Request = ServiceRequest<P>,
|
||||||
|
Response = ServiceRequest<P1>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
F: IntoNewService<C>,
|
||||||
|
{
|
||||||
|
let chain = self.chain.and_then(chain.into_new_service());
|
||||||
App {
|
App {
|
||||||
|
chain,
|
||||||
|
state: self.state,
|
||||||
|
extensions: self.extensions,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Complete applicatin chain configuration and start resource
|
||||||
|
/// configuration.
|
||||||
|
pub fn router<B>(self) -> AppRouter<T, P, B, AppEntry<P>> {
|
||||||
|
let fref = Rc::new(RefCell::new(None));
|
||||||
|
AppRouter {
|
||||||
|
chain: self.chain,
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
default: None,
|
default: None,
|
||||||
defaults: Vec::new(),
|
defaults: Vec::new(),
|
||||||
endpoint: AppEntry::new(fref.clone()),
|
endpoint: AppEntry::new(fref.clone()),
|
||||||
factory_ref: fref,
|
factory_ref: fref,
|
||||||
extensions: Extensions::new(),
|
extensions: self.extensions,
|
||||||
state: Vec::new(),
|
state: self.state,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Application router builder
|
/// Structure that follows the builder pattern for building application
|
||||||
// pub struct AppRouter<S, T, P> {
|
/// instances.
|
||||||
// services: Vec<(
|
pub struct AppRouter<C, P, B, T> {
|
||||||
// ResourceDef,
|
chain: C,
|
||||||
// BoxedHttpNewService<ServiceRequest<P>, Response>,
|
services: Vec<(ResourceDef, HttpNewService<P>)>,
|
||||||
// )>,
|
default: Option<Rc<HttpNewService<P>>>,
|
||||||
// default: Option<Rc<HttpDefaultNewService<ServiceRequest<P>, Response>>>,
|
defaults: Vec<Rc<RefCell<Option<Rc<HttpNewService<P>>>>>>,
|
||||||
// defaults:
|
endpoint: T,
|
||||||
// Vec<Rc<RefCell<Option<Rc<HttpDefaultNewService<ServiceRequest<P>, Response>>>>>>,
|
factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
||||||
// state: AppState<S>,
|
extensions: Extensions,
|
||||||
// endpoint: T,
|
state: Vec<Box<StateFactory>>,
|
||||||
// factory_ref: Rc<RefCell<Option<AppFactory<P>>>>,
|
_t: PhantomData<(P, B)>,
|
||||||
// extensions: Extensions,
|
}
|
||||||
// _t: PhantomData<P>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl<P, B, T> App<P, B, T>
|
impl<C, P, B, T> AppRouter<C, P, B, T>
|
||||||
where
|
where
|
||||||
P: 'static,
|
P: 'static,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
@ -221,7 +368,8 @@ where
|
|||||||
pub fn middleware<M, B1, F>(
|
pub fn middleware<M, B1, F>(
|
||||||
self,
|
self,
|
||||||
mw: F,
|
mw: F,
|
||||||
) -> App<
|
) -> AppRouter<
|
||||||
|
C,
|
||||||
P,
|
P,
|
||||||
B1,
|
B1,
|
||||||
impl NewService<
|
impl NewService<
|
||||||
@ -243,14 +391,15 @@ where
|
|||||||
F: IntoNewTransform<M, T::Service>,
|
F: IntoNewTransform<M, T::Service>,
|
||||||
{
|
{
|
||||||
let endpoint = ApplyNewService::new(mw, self.endpoint);
|
let endpoint = ApplyNewService::new(mw, self.endpoint);
|
||||||
App {
|
AppRouter {
|
||||||
endpoint,
|
endpoint,
|
||||||
|
chain: self.chain,
|
||||||
state: self.state,
|
state: self.state,
|
||||||
services: self.services,
|
services: self.services,
|
||||||
default: self.default,
|
default: self.default,
|
||||||
defaults: Vec::new(),
|
defaults: self.defaults,
|
||||||
factory_ref: self.factory_ref,
|
factory_ref: self.factory_ref,
|
||||||
extensions: Extensions::new(),
|
extensions: self.extensions,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,8 +441,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, P: 'static, B: MessageBody>
|
impl<C, T, P: 'static, B: MessageBody>
|
||||||
IntoNewService<AndThenNewService<AppStateFactory<P>, T, ()>> for App<P, B, T>
|
IntoNewService<AndThenNewService<AppInit<C, P>, T, ()>> for AppRouter<C, P, B, T>
|
||||||
where
|
where
|
||||||
T: NewService<
|
T: NewService<
|
||||||
Request = ServiceRequest<P>,
|
Request = ServiceRequest<P>,
|
||||||
@ -301,8 +450,14 @@ where
|
|||||||
Error = (),
|
Error = (),
|
||||||
InitError = (),
|
InitError = (),
|
||||||
>,
|
>,
|
||||||
|
C: NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P>,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
{
|
{
|
||||||
fn into_new_service(self) -> AndThenNewService<AppStateFactory<P>, T, ()> {
|
fn into_new_service(self) -> AndThenNewService<AppInit<C, P>, T, ()> {
|
||||||
// update resource default service
|
// update resource default service
|
||||||
if self.default.is_some() {
|
if self.default.is_some() {
|
||||||
for default in &self.defaults {
|
for default in &self.defaults {
|
||||||
@ -317,99 +472,15 @@ where
|
|||||||
services: Rc::new(self.services),
|
services: Rc::new(self.services),
|
||||||
});
|
});
|
||||||
|
|
||||||
AppStateFactory {
|
AppInit {
|
||||||
|
chain: self.chain,
|
||||||
state: self.state,
|
state: self.state,
|
||||||
extensions: Rc::new(RefCell::new(Rc::new(self.extensions))),
|
extensions: Rc::new(RefCell::new(Rc::new(self.extensions))),
|
||||||
_t: PhantomData,
|
|
||||||
}
|
}
|
||||||
.and_then(self.endpoint)
|
.and_then(self.endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Service factory to convert `Request` to a `ServiceRequest<S>`
|
|
||||||
pub struct AppStateFactory<P> {
|
|
||||||
state: Vec<Box<StateFactory>>,
|
|
||||||
extensions: Rc<RefCell<Rc<Extensions>>>,
|
|
||||||
_t: PhantomData<P>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: 'static> NewService for AppStateFactory<P> {
|
|
||||||
type Request = Request<P>;
|
|
||||||
type Response = ServiceRequest<P>;
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = AppStateService<P>;
|
|
||||||
type Future = AppStateFactoryResult<P>;
|
|
||||||
|
|
||||||
fn new_service(&self, _: &()) -> Self::Future {
|
|
||||||
AppStateFactoryResult {
|
|
||||||
state: self.state.iter().map(|s| s.construct()).collect(),
|
|
||||||
extensions: self.extensions.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct AppStateFactoryResult<P> {
|
|
||||||
state: Vec<Box<StateFactoryResult>>,
|
|
||||||
extensions: Rc<RefCell<Rc<Extensions>>>,
|
|
||||||
_t: PhantomData<P>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> Future for AppStateFactoryResult<P> {
|
|
||||||
type Item = AppStateService<P>;
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
if let Some(extensions) = Rc::get_mut(&mut *self.extensions.borrow_mut()) {
|
|
||||||
let mut idx = 0;
|
|
||||||
while idx < self.state.len() {
|
|
||||||
if let Async::Ready(_) = self.state[idx].poll_result(extensions)? {
|
|
||||||
self.state.remove(idx);
|
|
||||||
} else {
|
|
||||||
idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !self.state.is_empty() {
|
|
||||||
return Ok(Async::NotReady);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log::warn!("Multiple copies of app extensions exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Async::Ready(AppStateService {
|
|
||||||
extensions: self.extensions.borrow().clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Service to convert `Request` to a `ServiceRequest<S>`
|
|
||||||
pub struct AppStateService<P> {
|
|
||||||
extensions: Rc<Extensions>,
|
|
||||||
_t: PhantomData<P>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> Service for AppStateService<P> {
|
|
||||||
type Request = Request<P>;
|
|
||||||
type Response = ServiceRequest<P>;
|
|
||||||
type Error = ();
|
|
||||||
type Future = FutureResult<Self::Response, Self::Error>;
|
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self, req: Request<P>) -> Self::Future {
|
|
||||||
ok(ServiceRequest::new(
|
|
||||||
Path::new(Url::new(req.uri().clone())),
|
|
||||||
req,
|
|
||||||
self.extensions.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AppFactory<P> {
|
pub struct AppFactory<P> {
|
||||||
services: Rc<Vec<(ResourceDef, HttpNewService<P>)>>,
|
services: Rc<Vec<(ResourceDef, HttpNewService<P>)>>,
|
||||||
}
|
}
|
||||||
@ -530,17 +601,6 @@ impl<P> Service for AppService<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppServiceResponse(Box<Future<Item = ServiceResponse, Error = ()>>);
|
|
||||||
|
|
||||||
impl Future for AppServiceResponse {
|
|
||||||
type Item = ServiceResponse;
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
self.0.poll().map_err(|_| panic!())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct AppEntry<P> {
|
pub struct AppEntry<P> {
|
||||||
factory: Rc<RefCell<Option<AppFactory<P>>>>,
|
factory: Rc<RefCell<Option<AppFactory<P>>>>,
|
||||||
@ -564,3 +624,151 @@ impl<P: 'static> NewService for AppEntry<P> {
|
|||||||
self.factory.borrow_mut().as_mut().unwrap().new_service(&())
|
self.factory.borrow_mut().as_mut().unwrap().new_service(&())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AppChain;
|
||||||
|
|
||||||
|
impl NewService<()> for AppChain {
|
||||||
|
type Request = ServiceRequest<PayloadStream>;
|
||||||
|
type Response = ServiceRequest<PayloadStream>;
|
||||||
|
type Error = ();
|
||||||
|
type InitError = ();
|
||||||
|
type Service = AppChain;
|
||||||
|
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: &()) -> Self::Future {
|
||||||
|
ok(AppChain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Service for AppChain {
|
||||||
|
type Request = ServiceRequest<PayloadStream>;
|
||||||
|
type Response = ServiceRequest<PayloadStream>;
|
||||||
|
type Error = ();
|
||||||
|
type Future = FutureResult<Self::Response, Self::Error>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
|
Ok(Async::Ready(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
|
ok(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Service factory to convert `Request` to a `ServiceRequest<S>`
|
||||||
|
pub struct AppInit<C, P>
|
||||||
|
where
|
||||||
|
C: NewService<Request = ServiceRequest<PayloadStream>, Response = ServiceRequest<P>>,
|
||||||
|
{
|
||||||
|
chain: C,
|
||||||
|
state: Vec<Box<StateFactory>>,
|
||||||
|
extensions: Rc<RefCell<Rc<Extensions>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, P: 'static> NewService for AppInit<C, P>
|
||||||
|
where
|
||||||
|
C: NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P>,
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
type Request = Request<PayloadStream>;
|
||||||
|
type Response = ServiceRequest<P>;
|
||||||
|
type Error = C::Error;
|
||||||
|
type InitError = C::InitError;
|
||||||
|
type Service = AppInitService<C::Service, P>;
|
||||||
|
type Future = AppInitResult<C, P>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: &()) -> Self::Future {
|
||||||
|
AppInitResult {
|
||||||
|
chain: self.chain.new_service(&()),
|
||||||
|
state: self.state.iter().map(|s| s.construct()).collect(),
|
||||||
|
extensions: self.extensions.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AppInitResult<C, P>
|
||||||
|
where
|
||||||
|
C: NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P>,
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
chain: C::Future,
|
||||||
|
state: Vec<Box<StateFactoryResult>>,
|
||||||
|
extensions: Rc<RefCell<Rc<Extensions>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, P> Future for AppInitResult<C, P>
|
||||||
|
where
|
||||||
|
C: NewService<
|
||||||
|
Request = ServiceRequest<PayloadStream>,
|
||||||
|
Response = ServiceRequest<P>,
|
||||||
|
InitError = (),
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
type Item = AppInitService<C::Service, P>;
|
||||||
|
type Error = C::InitError;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
|
if let Some(extensions) = Rc::get_mut(&mut *self.extensions.borrow_mut()) {
|
||||||
|
let mut idx = 0;
|
||||||
|
while idx < self.state.len() {
|
||||||
|
if let Async::Ready(_) = self.state[idx].poll_result(extensions)? {
|
||||||
|
self.state.remove(idx);
|
||||||
|
} else {
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !self.state.is_empty() {
|
||||||
|
return Ok(Async::NotReady);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!("Multiple copies of app extensions exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
let chain = futures::try_ready!(self.chain.poll());
|
||||||
|
|
||||||
|
Ok(Async::Ready(AppInitService {
|
||||||
|
chain,
|
||||||
|
extensions: self.extensions.borrow().clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Service to convert `Request` to a `ServiceRequest<S>`
|
||||||
|
pub struct AppInitService<C, P>
|
||||||
|
where
|
||||||
|
C: Service<Request = ServiceRequest<PayloadStream>, Response = ServiceRequest<P>>,
|
||||||
|
{
|
||||||
|
chain: C,
|
||||||
|
extensions: Rc<Extensions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, P> Service for AppInitService<C, P>
|
||||||
|
where
|
||||||
|
C: Service<Request = ServiceRequest<PayloadStream>, Response = ServiceRequest<P>>,
|
||||||
|
{
|
||||||
|
type Request = Request<PayloadStream>;
|
||||||
|
type Response = ServiceRequest<P>;
|
||||||
|
type Error = C::Error;
|
||||||
|
type Future = C::Future;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
|
self.chain.poll_ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request<PayloadStream>) -> Self::Future {
|
||||||
|
let req = ServiceRequest::new(
|
||||||
|
Path::new(Url::new(req.uri().clone())),
|
||||||
|
req,
|
||||||
|
self.extensions.clone(),
|
||||||
|
);
|
||||||
|
self.chain.call(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,7 +24,7 @@ lazy_static::lazy_static! {
|
|||||||
Mutex::new(
|
Mutex::new(
|
||||||
threadpool::Builder::new()
|
threadpool::Builder::new()
|
||||||
.thread_name("actix-web".to_owned())
|
.thread_name("actix-web".to_owned())
|
||||||
.num_threads(8)
|
.num_threads(default)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -45,11 +45,15 @@ pub enum BlockingError<E> {
|
|||||||
/// to result of the function execution.
|
/// to result of the function execution.
|
||||||
pub fn run<F, I, E>(f: F) -> CpuFuture<I, E>
|
pub fn run<F, I, E>(f: F) -> CpuFuture<I, E>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<I, E>,
|
F: FnOnce() -> Result<I, E> + Send + 'static,
|
||||||
|
I: Send + 'static,
|
||||||
|
E: Send + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
POOL.with(move |pool| {
|
POOL.with(|pool| {
|
||||||
|
pool.execute(move || {
|
||||||
let _ = tx.send(f());
|
let _ = tx.send(f());
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
CpuFuture { rx }
|
CpuFuture { rx }
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{fmt, str};
|
use std::{fmt, str};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![allow(clippy::type_complexity, dead_code, unused_variables)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod extractor;
|
mod extractor;
|
||||||
@ -28,7 +28,7 @@ pub use crate::service::{ServiceRequest, ServiceResponse};
|
|||||||
pub use crate::state::State;
|
pub use crate::state::State;
|
||||||
|
|
||||||
pub mod dev {
|
pub mod dev {
|
||||||
pub use crate::app::AppService;
|
pub use crate::app::AppRouter;
|
||||||
pub use crate::handler::{AsyncFactory, Extract, Factory, Handle};
|
pub use crate::handler::{AsyncFactory, Extract, Factory, Handle};
|
||||||
pub use crate::route::{Route, RouteBuilder};
|
pub use crate::route::{Route, RouteBuilder};
|
||||||
// pub use crate::info::ConnectionInfo;
|
// pub use crate::info::ConnectionInfo;
|
||||||
|
@ -117,7 +117,6 @@ where
|
|||||||
enum EncoderBody<B> {
|
enum EncoderBody<B> {
|
||||||
Body(B),
|
Body(B),
|
||||||
Other(Box<dyn MessageBody>),
|
Other(Box<dyn MessageBody>),
|
||||||
None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Encoder<B> {
|
pub struct Encoder<B> {
|
||||||
@ -131,7 +130,6 @@ impl<B: MessageBody> MessageBody for Encoder<B> {
|
|||||||
match self.body {
|
match self.body {
|
||||||
EncoderBody::Body(ref b) => b.length(),
|
EncoderBody::Body(ref b) => b.length(),
|
||||||
EncoderBody::Other(ref b) => b.length(),
|
EncoderBody::Other(ref b) => b.length(),
|
||||||
EncoderBody::None => BodyLength::Empty,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BodyLength::Stream
|
BodyLength::Stream
|
||||||
@ -143,7 +141,6 @@ impl<B: MessageBody> MessageBody for Encoder<B> {
|
|||||||
let result = match self.body {
|
let result = match self.body {
|
||||||
EncoderBody::Body(ref mut b) => b.poll_next()?,
|
EncoderBody::Body(ref mut b) => b.poll_next()?,
|
||||||
EncoderBody::Other(ref mut b) => b.poll_next()?,
|
EncoderBody::Other(ref mut b) => b.poll_next()?,
|
||||||
EncoderBody::None => return Ok(Async::Ready(None)),
|
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Async::NotReady => return Ok(Async::NotReady),
|
Async::NotReady => return Ok(Async::NotReady),
|
||||||
|
10
src/route.rs
10
src/route.rs
@ -320,11 +320,11 @@ impl<P: 'static> RouteBuilder<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RouteServiceBuilder<P, T, U1, U2> {
|
// pub struct RouteServiceBuilder<P, T, U1, U2> {
|
||||||
service: T,
|
// service: T,
|
||||||
filters: Vec<Box<Filter>>,
|
// filters: Vec<Box<Filter>>,
|
||||||
_t: PhantomData<(P, U1, U2)>,
|
// _t: PhantomData<(P, U1, U2)>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
// impl<T, S: 'static, U1, U2> RouteServiceBuilder<T, S, U1, U2>
|
// impl<T, S: 'static, U1, U2> RouteServiceBuilder<T, S, U1, U2>
|
||||||
// where
|
// where
|
||||||
|
Loading…
Reference in New Issue
Block a user