diff --git a/examples/basic.rs b/examples/basic.rs index a18581f90..886efb7b4 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -2,7 +2,7 @@ use futures::IntoFuture; use actix_http::{h1, http::Method, Response}; use actix_server::Server; -use actix_web::{middleware, App, Error, HttpRequest, Resource}; +use actix_web::{middleware, web, App, Error, HttpRequest, Resource, Route}; fn index(req: HttpRequest) -> &'static str { println!("REQ: {:?}", req); @@ -31,7 +31,7 @@ fn main() { middleware::DefaultHeaders::new().header("X-Version", "0.2"), ) .middleware(middleware::Compress::default()) - .resource("/resource1/index.html", |r| r.get(index)) + .resource("/resource1/index.html", |r| r.route(web::get().to(index))) .service( "/resource2/index.html", Resource::new() @@ -39,8 +39,10 @@ fn main() { middleware::DefaultHeaders::new() .header("X-Version-R2", "0.3"), ) - .default_resource(|r| r.to(|| Response::MethodNotAllowed())) - .method(Method::GET, |r| r.to_async(index_async)), + .default_resource(|r| { + r.route(Route::new().to(|| Response::MethodNotAllowed())) + }) + .route(web::method(Method::GET).to_async(index_async)), ) .service("/test1.html", Resource::new().to(|| "Test\r\n")) .service("/", Resource::new().to(no_params)), diff --git a/src/app.rs b/src/app.rs index 2e45f2d3c..d92190915 100644 --- a/src/app.rs +++ b/src/app.rs @@ -159,16 +159,16 @@ where } /// Register a middleware. - pub fn middleware( + pub fn middleware( self, mw: F, ) -> AppRouter< T, P, - Body, + B, impl NewService< Request = ServiceRequest

, - Response = ServiceResponse, + Response = ServiceResponse, Error = (), InitError = (), >, @@ -177,7 +177,7 @@ where M: NewTransform< AppService

, Request = ServiceRequest

, - Response = ServiceResponse, + Response = ServiceResponse, Error = (), InitError = (), >, diff --git a/src/extractor.rs b/src/extractor.rs index 48c70b861..522ce721f 100644 --- a/src/extractor.rs +++ b/src/extractor.rs @@ -26,7 +26,7 @@ use actix_router::PathDeserializer; use crate::handler::FromRequest; use crate::request::HttpRequest; use crate::responder::Responder; -use crate::service::ServiceRequest; +use crate::service::ServiceFromRequest; #[derive(PartialEq, Eq, PartialOrd, Ord)] /// Extract typed information from the request's path. @@ -112,7 +112,7 @@ impl Path { } /// Extract path information from a request - pub fn extract

(req: &ServiceRequest

) -> Result, de::value::Error> + pub fn extract

(req: &ServiceFromRequest

) -> Result, de::value::Error> where T: DeserializeOwned, { @@ -135,7 +135,7 @@ where type Future = FutureResult; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { Self::extract(req).map_err(ErrorNotFound).into_future() } } @@ -221,7 +221,7 @@ where type Future = FutureResult; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { serde_urlencoded::from_str::(req.query_string()) .map(|val| ok(Query(val))) .unwrap_or_else(|e| err(e.into())) @@ -301,7 +301,7 @@ where type Future = Box>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { let cfg = FormConfig::default(); let req2 = req.clone(); @@ -511,7 +511,7 @@ where type Future = Box>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { let cfg = JsonConfig::default(); let req2 = req.clone(); @@ -619,7 +619,7 @@ where Either>, FutureResult>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { let cfg = PayloadConfig::default(); if let Err(e) = cfg.check_mimetype(req) { @@ -666,7 +666,7 @@ where Either>, FutureResult>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { let cfg = PayloadConfig::default(); // check content-type @@ -755,7 +755,7 @@ where type Future = Box, Error = Error>>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { Box::new(T::from_request(req).then(|r| match r { Ok(v) => future::ok(Some(v)), Err(_) => future::ok(None), @@ -818,7 +818,7 @@ where type Future = Box, Error = Error>>; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { Box::new(T::from_request(req).then(|res| match res { Ok(v) => ok(Ok(v)), Err(e) => ok(Err(e)), @@ -846,7 +846,7 @@ impl PayloadConfig { self } - fn check_mimetype

(&self, req: &ServiceRequest

) -> Result<(), Error> { + fn check_mimetype

(&self, req: &ServiceFromRequest

) -> Result<(), Error> { // check content-type if let Some(ref mt) = self.mimetype { match req.mime_type() { @@ -884,7 +884,7 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => { type Error = Error; type Future = $fut_type; - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { $fut_type { items: <($(Option<$T>,)+)>::default(), futs: ($($T::from_request(req),)+), @@ -933,7 +933,7 @@ impl

FromRequest

for () { type Error = Error; type Future = FutureResult<(), Error>; - fn from_request(_req: &mut ServiceRequest

) -> Self::Future { + fn from_request(_req: &mut ServiceFromRequest

) -> Self::Future { ok(()) } } diff --git a/src/filter.rs b/src/filter.rs index 37c23d732..e3d87b766 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,8 +1,7 @@ //! Route match predicates #![allow(non_snake_case)] use actix_http::http::{self, header, HttpTryFrom}; - -use crate::request::HttpRequest; +use actix_http::RequestHead; /// Trait defines resource predicate. /// Predicate can modify request object. It is also possible to @@ -10,20 +9,21 @@ use crate::request::HttpRequest; /// Extensions container available via `HttpRequest::extensions()` method. pub trait Filter { /// Check if request matches predicate - fn check(&self, request: &HttpRequest) -> bool; + fn check(&self, request: &RequestHead) -> bool; } /// Return filter that matches if any of supplied filters. /// -/// ```rust,ignore -/// use actix_web::{filter, App, HttpResponse}; +/// ```rust +/// use actix_web::{web, filter, App, HttpResponse}; /// /// fn main() { -/// App::new().resource("/index.html", |r| { -/// r.route() -/// .filter(pred::Any(pred::Get()).or(pred::Post())) -/// .to(|| HttpResponse::MethodNotAllowed()) -/// }); +/// App::new().resource("/index.html", |r| +/// r.route( +/// web::route() +/// .filter(filter::Any(filter::Get()).or(filter::Post())) +/// .to(|| HttpResponse::MethodNotAllowed())) +/// ); /// } /// ``` pub fn Any(filter: F) -> AnyFilter { @@ -42,7 +42,7 @@ impl AnyFilter { } impl Filter for AnyFilter { - fn check(&self, req: &HttpRequest) -> bool { + fn check(&self, req: &RequestHead) -> bool { for p in &self.0 { if p.check(req) { return true; @@ -56,15 +56,13 @@ impl Filter for AnyFilter { /// /// ```rust /// # extern crate actix_web; -/// use actix_web::{filter, App, HttpResponse}; +/// use actix_web::{filter, web, App, HttpResponse}; /// /// fn main() { /// App::new().resource("/index.html", |r| { -/// r.route( -/// |r| r.filter( -/// filter::All(filter::Get()) -/// .and(filter::Header("content-type", "text/plain")), -/// ) +/// r.route(web::route() +/// .filter( +/// filter::All(filter::Get()).and(filter::Header("content-type", "text/plain"))) /// .to(|| HttpResponse::MethodNotAllowed())) /// }); /// } @@ -85,7 +83,7 @@ impl AllFilter { } impl Filter for AllFilter { - fn check(&self, request: &HttpRequest) -> bool { + fn check(&self, request: &RequestHead) -> bool { for p in &self.0 { if !p.check(request) { return false; @@ -104,7 +102,7 @@ pub fn Not(filter: F) -> NotFilter { pub struct NotFilter(Box); impl Filter for NotFilter { - fn check(&self, request: &HttpRequest) -> bool { + fn check(&self, request: &RequestHead) -> bool { !self.0.check(request) } } @@ -114,8 +112,8 @@ impl Filter for NotFilter { pub struct MethodFilter(http::Method); impl Filter for MethodFilter { - fn check(&self, request: &HttpRequest) -> bool { - request.method() == self.0 + fn check(&self, request: &RequestHead) -> bool { + request.method == self.0 } } @@ -182,8 +180,8 @@ pub fn Header(name: &'static str, value: &'static str) -> HeaderFilter { pub struct HeaderFilter(header::HeaderName, header::HeaderValue); impl Filter for HeaderFilter { - fn check(&self, req: &HttpRequest) -> bool { - if let Some(val) = req.headers().get(&self.0) { + fn check(&self, req: &RequestHead) -> bool { + if let Some(val) = req.headers.get(&self.0) { return val == self.1; } false @@ -219,7 +217,7 @@ impl Filter for HeaderFilter { // } // impl Filter for HostFilter { -// fn check(&self, _req: &HttpRequest) -> bool { +// fn check(&self, _req: &RequestHead) -> bool { // // let info = req.connection_info(); // // if let Some(ref scheme) = self.1 { // // self.0 == info.host() && scheme == info.scheme() diff --git a/src/handler.rs b/src/handler.rs index 8076d4d42..31ae796b2 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -7,7 +7,7 @@ use futures::{try_ready, Async, Future, IntoFuture, Poll}; use crate::request::HttpRequest; use crate::responder::Responder; -use crate::service::{ServiceRequest, ServiceResponse}; +use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; /// Trait implemented by types that can be extracted from request. /// @@ -20,7 +20,7 @@ pub trait FromRequest

: Sized { type Future: Future; /// Convert request to a Self - fn from_request(req: &mut ServiceRequest

) -> Self::Future; + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future; } /// Handler converter factory @@ -306,7 +306,7 @@ impl> Default for Extract { impl> NewService for Extract { type Request = ServiceRequest

; type Response = (T, HttpRequest); - type Error = (Error, ServiceRequest

); + type Error = (Error, ServiceFromRequest

); type InitError = (); type Service = ExtractService; type Future = FutureResult; @@ -323,14 +323,15 @@ pub struct ExtractService> { impl> Service for ExtractService { type Request = ServiceRequest

; type Response = (T, HttpRequest); - type Error = (Error, ServiceRequest

); + type Error = (Error, ServiceFromRequest

); type Future = ExtractResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } - fn call(&mut self, mut req: ServiceRequest

) -> Self::Future { + fn call(&mut self, req: ServiceRequest

) -> Self::Future { + let mut req = req.into(); ExtractResponse { fut: T::from_request(&mut req), req: Some(req), @@ -339,13 +340,13 @@ impl> Service for ExtractService { } pub struct ExtractResponse> { - req: Option>, + req: Option>, fut: T::Future, } impl> Future for ExtractResponse { type Item = (T, HttpRequest); - type Error = (Error, ServiceRequest

); + type Error = (Error, ServiceFromRequest

); fn poll(&mut self) -> Poll { let item = try_ready!(self diff --git a/src/lib.rs b/src/lib.rs index 70ce96073..0e81b65ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,12 +25,91 @@ pub use crate::handler::FromRequest; pub use crate::request::HttpRequest; pub use crate::resource::Resource; pub use crate::responder::{Either, Responder}; +pub use crate::route::Route; pub use crate::service::{ServiceRequest, ServiceResponse}; pub use crate::state::State; +pub mod web { + use actix_http::{http::Method, Error, Response}; + use futures::IntoFuture; + + use crate::handler::{AsyncFactory, Factory, FromRequest}; + use crate::responder::Responder; + use crate::Route; + + pub fn route() -> Route

{ + Route::new() + } + + pub fn get() -> Route

{ + Route::get() + } + + pub fn post() -> Route

{ + Route::post() + } + + pub fn put() -> Route

{ + Route::put() + } + + pub fn delete() -> Route

{ + Route::delete() + } + + pub fn head() -> Route

{ + Route::new().method(Method::HEAD) + } + + pub fn method(method: Method) -> Route

{ + Route::new().method(method) + } + + /// Create a new route and add handler. + /// + /// ```rust + /// use actix_web::{web, App, HttpResponse}; + /// + /// fn index() -> HttpResponse { + /// unimplemented!() + /// } + /// + /// App::new().resource("/", |r| r.route(web::to(index))); + /// ``` + pub fn to(handler: F) -> Route

+ where + F: Factory + 'static, + I: FromRequest

+ 'static, + R: Responder + 'static, + { + Route::new().to(handler) + } + + /// Create a new route and add async handler. + /// + /// ```rust + /// use actix_web::{web, App, HttpResponse, Error}; + /// + /// fn index() -> impl futures::Future { + /// futures::future::ok(HttpResponse::Ok().finish()) + /// } + /// + /// App::new().resource("/", |r| r.route(web::to_async(index))); + /// ``` + pub fn to_async(handler: F) -> Route

+ where + F: AsyncFactory, + I: FromRequest

+ 'static, + R: IntoFuture + 'static, + R::Item: Into, + R::Error: Into, + { + Route::new().to_async(handler) + } +} + pub mod dev { pub use crate::app::AppRouter; pub use crate::handler::{AsyncFactory, Extract, Factory, Handle}; - pub use crate::route::{Route, RouteBuilder}; // pub use crate::info::ConnectionInfo; } diff --git a/src/request.rs b/src/request.rs index 571431cc2..538064f19 100644 --- a/src/request.rs +++ b/src/request.rs @@ -9,11 +9,11 @@ use actix_router::{Path, Url}; use futures::future::{ok, FutureResult}; use crate::handler::FromRequest; -use crate::service::ServiceRequest; +use crate::service::ServiceFromRequest; #[derive(Clone)] pub struct HttpRequest { - head: Message, + pub(crate) head: Message, pub(crate) path: Path, extensions: Rc, } @@ -145,7 +145,7 @@ impl

FromRequest

for HttpRequest { type Future = FutureResult; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { ok(req.clone()) } } diff --git a/src/resource.rs b/src/resource.rs index 80ac8d83b..ab6096c52 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::rc::Rc; -use actix_http::{http::Method, Error, Response}; +use actix_http::{Error, Response}; use actix_service::boxed::{self, BoxedNewService, BoxedService}; use actix_service::{ ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service, @@ -11,7 +11,7 @@ use futures::{Async, Future, IntoFuture, Poll}; use crate::handler::{AsyncFactory, Factory, FromRequest}; use crate::responder::Responder; -use crate::route::{CreateRouteService, Route, RouteBuilder, RouteService}; +use crate::route::{CreateRouteService, Route, RouteService}; use crate::service::{ServiceRequest, ServiceResponse}; type HttpService

= BoxedService, ServiceResponse, ()>; @@ -74,92 +74,8 @@ where /// .finish(); /// } /// ``` - pub fn route(mut self, f: F) -> Self - where - F: FnOnce(RouteBuilder

) -> Route

, - { - self.routes.push(f(Route::build())); - self - } - - /// Register a new `GET` route. - pub fn get(mut self, f: F) -> Self - where - F: Factory + 'static, - I: FromRequest

+ 'static, - R: Responder + 'static, - { - self.routes.push(Route::get().to(f)); - self - } - - /// Register a new `POST` route. - pub fn post(mut self, f: F) -> Self - where - F: Factory + 'static, - I: FromRequest

+ 'static, - R: Responder + 'static, - { - self.routes.push(Route::post().to(f)); - self - } - - /// Register a new `PUT` route. - pub fn put(mut self, f: F) -> Self - where - F: Factory + 'static, - I: FromRequest

+ 'static, - R: Responder + 'static, - { - self.routes.push(Route::put().to(f)); - self - } - - /// Register a new `DELETE` route. - pub fn delete(mut self, f: F) -> Self - where - F: Factory + 'static, - I: FromRequest

+ 'static, - R: Responder + 'static, - { - self.routes.push(Route::delete().to(f)); - self - } - - /// Register a new `HEAD` route. - pub fn head(mut self, f: F) -> Self - where - F: Factory + 'static, - I: FromRequest

+ 'static, - R: Responder + 'static, - { - self.routes.push(Route::build().method(Method::HEAD).to(f)); - self - } - - /// Register a new route and add method check to route. - /// - /// ```rust,ignore - /// # extern crate actix_web; - /// use actix_web::*; - /// fn index(req: &HttpRequest) -> HttpResponse { unimplemented!() } - /// - /// App::new().resource("/", |r| r.method(http::Method::GET).f(index)); - /// ``` - /// - /// This is shortcut for: - /// - /// ```rust,ignore - /// # extern crate actix_web; - /// # use actix_web::*; - /// # fn index(req: &HttpRequest) -> HttpResponse { unimplemented!() } - /// App::new().resource("/", |r| r.route().filter(pred::Get()).f(index)); - /// ``` - pub fn method(mut self, method: Method, f: F) -> Self - where - F: FnOnce(RouteBuilder

) -> Route

, - { - self.routes.push(f(Route::build().method(method))); + pub fn route(mut self, route: Route

) -> Self { + self.routes.push(route); self } @@ -187,7 +103,7 @@ where I: FromRequest

+ 'static, R: Responder + 'static, { - self.routes.push(Route::build().to(handler)); + self.routes.push(Route::new().to(handler)); self } @@ -227,7 +143,7 @@ where R::Item: Into, R::Error: Into, { - self.routes.push(Route::build().to_async(handler)); + self.routes.push(Route::new().to_async(handler)); self } diff --git a/src/route.rs b/src/route.rs index d5e114246..99117afed 100644 --- a/src/route.rs +++ b/src/route.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use std::rc::Rc; use actix_http::{http::Method, Error, Response}; @@ -8,7 +7,8 @@ use futures::{Async, Future, IntoFuture, Poll}; use crate::filter::{self, Filter}; use crate::handler::{AsyncFactory, AsyncHandle, Extract, Factory, FromRequest, Handle}; use crate::responder::Responder; -use crate::service::{ServiceRequest, ServiceResponse}; +use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; +use crate::HttpResponse; type BoxedRouteService = Box< Service< @@ -40,24 +40,29 @@ pub struct Route

{ } impl Route

{ - pub fn build() -> RouteBuilder

{ - RouteBuilder::new() + pub fn new() -> Route

{ + Route { + service: Box::new(RouteNewService::new(Extract::new().and_then( + Handle::new(|| HttpResponse::NotFound()).map_err(|_| panic!()), + ))), + filters: Rc::new(Vec::new()), + } } - pub fn get() -> RouteBuilder

{ - RouteBuilder::new().method(Method::GET) + pub fn get() -> Route

{ + Route::new().method(Method::GET) } - pub fn post() -> RouteBuilder

{ - RouteBuilder::new().method(Method::POST) + pub fn post() -> Route

{ + Route::new().method(Method::POST) } - pub fn put() -> RouteBuilder

{ - RouteBuilder::new().method(Method::PUT) + pub fn put() -> Route

{ + Route::new().method(Method::PUT) } - pub fn delete() -> RouteBuilder

{ - RouteBuilder::new().method(Method::DELETE) + pub fn delete() -> Route

{ + Route::new().method(Method::DELETE) } } @@ -109,7 +114,7 @@ pub struct RouteService

{ impl

RouteService

{ pub fn check(&self, req: &mut ServiceRequest

) -> bool { for f in self.filters.iter() { - if !f.check(req.request()) { + if !f.check(req.head()) { return false; } } @@ -132,19 +137,7 @@ impl

Service for RouteService

{ } } -pub struct RouteBuilder

{ - filters: Vec>, - _t: PhantomData

, -} - -impl RouteBuilder

{ - fn new() -> RouteBuilder

{ - RouteBuilder { - filters: Vec::new(), - _t: PhantomData, - } - } - +impl Route

{ /// Add method match filter to the route. /// /// ```rust,ignore @@ -161,7 +154,9 @@ impl RouteBuilder

{ /// # } /// ``` pub fn method(mut self, method: Method) -> Self { - self.filters.push(Box::new(filter::Method(method))); + Rc::get_mut(&mut self.filters) + .unwrap() + .push(Box::new(filter::Method(method))); self } @@ -181,7 +176,7 @@ impl RouteBuilder

{ /// # } /// ``` pub fn filter(mut self, f: F) -> Self { - self.filters.push(Box::new(f)); + Rc::get_mut(&mut self.filters).unwrap().push(Box::new(f)); self } @@ -259,18 +254,16 @@ impl RouteBuilder

{ /// ); // <- use `with` extractor /// } /// ``` - pub fn to(self, handler: F) -> Route

+ pub fn to(mut self, handler: F) -> Route

where F: Factory + 'static, T: FromRequest

+ 'static, R: Responder + 'static, { - Route { - service: Box::new(RouteNewService::new( - Extract::new().and_then(Handle::new(handler).map_err(|_| panic!())), - )), - filters: Rc::new(self.filters), - } + self.service = Box::new(RouteNewService::new( + Extract::new().and_then(Handle::new(handler).map_err(|_| panic!())), + )); + self } /// Set async handler function, use request extractor for parameters. @@ -303,7 +296,7 @@ impl RouteBuilder

{ /// } /// ``` #[allow(clippy::wrong_self_convention)] - pub fn to_async(self, handler: F) -> Route

+ pub fn to_async(mut self, handler: F) -> Self where F: AsyncFactory, T: FromRequest

+ 'static, @@ -311,12 +304,10 @@ impl RouteBuilder

{ R::Item: Into, R::Error: Into, { - Route { - service: Box::new(RouteNewService::new( - Extract::new().and_then(AsyncHandle::new(handler).map_err(|_| panic!())), - )), - filters: Rc::new(self.filters), - } + self.service = Box::new(RouteNewService::new( + Extract::new().and_then(AsyncHandle::new(handler).map_err(|_| panic!())), + )); + self } } @@ -450,7 +441,7 @@ impl RouteBuilder

{ struct RouteNewService where - T: NewService, Error = (Error, ServiceRequest

)>, + T: NewService, Error = (Error, ServiceFromRequest

)>, { service: T, } @@ -460,7 +451,7 @@ where T: NewService< Request = ServiceRequest

, Response = ServiceResponse, - Error = (Error, ServiceRequest

), + Error = (Error, ServiceFromRequest

), >, T::Future: 'static, T::Service: 'static, @@ -476,7 +467,7 @@ where T: NewService< Request = ServiceRequest

, Response = ServiceResponse, - Error = (Error, ServiceRequest

), + Error = (Error, ServiceFromRequest

), >, T::Future: 'static, T::Service: 'static, @@ -513,7 +504,7 @@ where T: Service< Request = ServiceRequest

, Response = ServiceResponse, - Error = (Error, ServiceRequest

), + Error = (Error, ServiceFromRequest

), >, { type Request = ServiceRequest

; diff --git a/src/service.rs b/src/service.rs index 775bb6113..078cb2236 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,9 +1,11 @@ +use std::cell::{Ref, RefMut}; use std::rc::Rc; use actix_http::body::{Body, MessageBody, ResponseBody}; -use actix_http::http::HeaderMap; +use actix_http::http::{HeaderMap, Method, Uri, Version}; use actix_http::{ - Error, Extensions, HttpMessage, Payload, Request, Response, ResponseHead, + Error, Extensions, HttpMessage, Payload, Request, RequestHead, Response, + ResponseHead, }; use actix_router::{Path, Url}; @@ -27,11 +29,6 @@ impl

ServiceRequest

{ } } - #[inline] - pub fn request(&self) -> &HttpRequest { - &self.req - } - #[inline] pub fn into_request(self) -> HttpRequest { self.req @@ -49,10 +46,93 @@ impl

ServiceRequest

{ ServiceResponse::new(self.req, err.into().into()) } + /// This method returns reference to the request head + #[inline] + pub fn head(&self) -> &RequestHead { + &self.req.head + } + + /// This method returns reference to the request head + #[inline] + pub fn head_mut(&mut self) -> &mut RequestHead { + &mut self.req.head + } + + /// Request's uri. + #[inline] + pub fn uri(&self) -> &Uri { + &self.head().uri + } + + /// Read the Request method. + #[inline] + pub fn method(&self) -> &Method { + &self.head().method + } + + /// Read the Request Version. + #[inline] + pub fn version(&self) -> Version { + self.head().version + } + + /// The target path of this Request. + #[inline] + pub fn path(&self) -> &str { + self.head().uri.path() + } + + #[inline] + /// Returns Request's headers. + pub fn headers(&self) -> &HeaderMap { + &self.head().headers + } + + /// The query string in the URL. + /// + /// E.g., id=10 + #[inline] + pub fn query_string(&self) -> &str { + if let Some(query) = self.uri().query().as_ref() { + query + } else { + "" + } + } + + /// Get a reference to the Path parameters. + /// + /// Params is a container for url parameters. + /// 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. + #[inline] + pub fn match_info(&self) -> &Path { + &self.req.path + } + #[inline] pub fn match_info_mut(&mut self) -> &mut Path { &mut self.req.path } + + /// Request extensions + #[inline] + pub fn extensions(&self) -> Ref { + self.req.head.extensions() + } + + /// Mutable reference to a the request's extensions + #[inline] + pub fn extensions_mut(&self) -> RefMut { + self.req.head.extensions_mut() + } + + /// Application extensions + #[inline] + pub fn app_extensions(&self) -> &Extensions { + self.req.app_extensions() + } } impl

HttpMessage for ServiceRequest

{ @@ -70,10 +150,65 @@ impl

HttpMessage for ServiceRequest

{ } impl

std::ops::Deref for ServiceRequest

{ + type Target = RequestHead; + + fn deref(&self) -> &RequestHead { + self.req.head() + } +} + +impl

std::ops::DerefMut for ServiceRequest

{ + fn deref_mut(&mut self) -> &mut RequestHead { + self.head_mut() + } +} + +pub struct ServiceFromRequest

{ + req: HttpRequest, + payload: Payload

, +} + +impl

ServiceFromRequest

{ + #[inline] + pub fn into_request(self) -> HttpRequest { + self.req + } + + /// Create service response for error + #[inline] + pub fn error_response>(self, err: E) -> ServiceResponse { + ServiceResponse::new(self.req, err.into().into()) + } +} + +impl

std::ops::Deref for ServiceFromRequest

{ type Target = HttpRequest; fn deref(&self) -> &HttpRequest { - self.request() + &self.req + } +} + +impl

HttpMessage for ServiceFromRequest

{ + type Stream = P; + + #[inline] + fn headers(&self) -> &HeaderMap { + self.req.headers() + } + + #[inline] + fn take_payload(&mut self) -> Payload { + std::mem::replace(&mut self.payload, Payload::None) + } +} + +impl

From> for ServiceFromRequest

{ + fn from(req: ServiceRequest

) -> Self { + Self { + req: req.req, + payload: req.payload, + } } } diff --git a/src/state.rs b/src/state.rs index 82aecc6e1..db2637775 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,7 +7,7 @@ use futures::future::{err, ok, FutureResult}; use futures::{Async, Future, IntoFuture, Poll}; use crate::handler::FromRequest; -use crate::service::ServiceRequest; +use crate::service::ServiceFromRequest; /// Application state factory pub(crate) trait StateFactory { @@ -50,7 +50,7 @@ impl FromRequest

for State { type Future = FutureResult; #[inline] - fn from_request(req: &mut ServiceRequest

) -> Self::Future { + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { if let Some(st) = req.app_extensions().get::>() { ok(st.clone()) } else { diff --git a/tests/test_server.rs b/tests/test_server.rs index 590cc0e7b..d28f207c1 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -12,7 +12,7 @@ use flate2::write::ZlibDecoder; use futures::stream::once; //Future, Stream use rand::{distributions::Alphanumeric, Rng}; -use actix_web::{middleware, App}; +use actix_web::{middleware, web, App}; const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ @@ -40,7 +40,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ fn test_body() { let mut srv = TestServer::new(|| { h1::H1Service::new( - App::new().resource("/", |r| r.get(|| Response::Ok().body(STR))), + App::new().resource("/", |r| r.route(web::to(|| Response::Ok().body(STR)))), ) }); @@ -59,7 +59,7 @@ fn test_body_gzip() { h1::H1Service::new( App::new() .middleware(middleware::Compress::new(ContentEncoding::Gzip)) - .resource("/", |r| r.get(|| Response::Ok().body(STR))), + .resource("/", |r| r.route(web::to(|| Response::Ok().body(STR)))), ) }); @@ -87,7 +87,9 @@ fn test_body_gzip_large() { h1::H1Service::new( App::new() .middleware(middleware::Compress::new(ContentEncoding::Gzip)) - .resource("/", |r| r.get(move || Response::Ok().body(data.clone()))), + .resource("/", |r| { + r.route(web::to(move || Response::Ok().body(data.clone()))) + }), ) }); @@ -118,7 +120,9 @@ fn test_body_gzip_large_random() { h1::H1Service::new( App::new() .middleware(middleware::Compress::new(ContentEncoding::Gzip)) - .resource("/", |r| r.get(move || Response::Ok().body(data.clone()))), + .resource("/", |r| { + r.route(web::to(move || Response::Ok().body(data.clone()))) + }), ) }); @@ -144,11 +148,11 @@ fn test_body_chunked_implicit() { App::new() .middleware(middleware::Compress::new(ContentEncoding::Gzip)) .resource("/", |r| { - r.get(move || { + r.route(web::get().to(move || { Response::Ok().streaming(once(Ok::<_, Error>( Bytes::from_static(STR.as_ref()), ))) - }) + })) }), ) }); @@ -178,11 +182,11 @@ fn test_body_br_streaming() { App::new() .middleware(middleware::Compress::new(ContentEncoding::Br)) .resource("/", |r| { - r.get(move || { + r.route(web::to(move || { Response::Ok().streaming(once(Ok::<_, Error>( Bytes::from_static(STR.as_ref()), ))) - }) + })) }), ) }); @@ -205,7 +209,7 @@ fn test_body_br_streaming() { fn test_head_binary() { let mut srv = TestServer::new(move || { h1::H1Service::new(App::new().resource("/", |r| { - r.head(move || Response::Ok().content_length(100).body(STR)) + r.route(web::head().to(move || Response::Ok().content_length(100).body(STR))) })) }); @@ -227,12 +231,12 @@ fn test_head_binary() { fn test_no_chunking() { let mut srv = TestServer::new(move || { h1::H1Service::new(App::new().resource("/", |r| { - r.get(move || { + r.route(web::to(move || { Response::Ok() .no_chunking() .content_length(STR.len() as u64) .streaming(once(Ok::<_, Error>(Bytes::from_static(STR.as_ref())))) - }) + })) })) }); @@ -252,7 +256,7 @@ fn test_body_deflate() { h1::H1Service::new( App::new() .middleware(middleware::Compress::new(ContentEncoding::Deflate)) - .resource("/", |r| r.get(move || Response::Ok().body(STR))), + .resource("/", |r| r.route(web::to(move || Response::Ok().body(STR)))), ) }); @@ -277,7 +281,7 @@ fn test_body_brotli() { h1::H1Service::new( App::new() .middleware(middleware::Compress::new(ContentEncoding::Br)) - .resource("/", |r| r.get(move || Response::Ok().body(STR))), + .resource("/", |r| r.route(web::to(move || Response::Ok().body(STR)))), ) });