mirror of
https://github.com/actix/actix-web.git
synced 2024-11-26 19:41:12 +00:00
use custom request for FromRequest trait
This commit is contained in:
parent
e4198a037a
commit
8103d33270
12 changed files with 342 additions and 216 deletions
|
@ -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)),
|
||||
|
|
|
@ -159,16 +159,16 @@ where
|
|||
}
|
||||
|
||||
/// Register a middleware.
|
||||
pub fn middleware<M, F>(
|
||||
pub fn middleware<M, B, F>(
|
||||
self,
|
||||
mw: F,
|
||||
) -> AppRouter<
|
||||
T,
|
||||
P,
|
||||
Body,
|
||||
B,
|
||||
impl NewService<
|
||||
Request = ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Response = ServiceResponse<B>,
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>,
|
||||
|
@ -177,7 +177,7 @@ where
|
|||
M: NewTransform<
|
||||
AppService<P>,
|
||||
Request = ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Response = ServiceResponse<B>,
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>,
|
||||
|
|
|
@ -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<T> Path<T> {
|
|||
}
|
||||
|
||||
/// Extract path information from a request
|
||||
pub fn extract<P>(req: &ServiceRequest<P>) -> Result<Path<T>, de::value::Error>
|
||||
pub fn extract<P>(req: &ServiceFromRequest<P>) -> Result<Path<T>, de::value::Error>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
|
@ -135,7 +135,7 @@ where
|
|||
type Future = FutureResult<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
Self::extract(req).map_err(ErrorNotFound).into_future()
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ where
|
|||
type Future = FutureResult<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
serde_urlencoded::from_str::<T>(req.query_string())
|
||||
.map(|val| ok(Query(val)))
|
||||
.unwrap_or_else(|e| err(e.into()))
|
||||
|
@ -301,7 +301,7 @@ where
|
|||
type Future = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = FormConfig::default();
|
||||
|
||||
let req2 = req.clone();
|
||||
|
@ -511,7 +511,7 @@ where
|
|||
type Future = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = JsonConfig::default();
|
||||
|
||||
let req2 = req.clone();
|
||||
|
@ -619,7 +619,7 @@ where
|
|||
Either<Box<Future<Item = Bytes, Error = Error>>, FutureResult<Bytes, Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = PayloadConfig::default();
|
||||
|
||||
if let Err(e) = cfg.check_mimetype(req) {
|
||||
|
@ -666,7 +666,7 @@ where
|
|||
Either<Box<Future<Item = String, Error = Error>>, FutureResult<String, Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = PayloadConfig::default();
|
||||
|
||||
// check content-type
|
||||
|
@ -755,7 +755,7 @@ where
|
|||
type Future = Box<Future<Item = Option<T>, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> 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<Future<Item = Result<T, T::Error>, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> 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<P>(&self, req: &ServiceRequest<P>) -> Result<(), Error> {
|
||||
fn check_mimetype<P>(&self, req: &ServiceFromRequest<P>) -> 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<P, $($T),+>;
|
||||
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
$fut_type {
|
||||
items: <($(Option<$T>,)+)>::default(),
|
||||
futs: ($($T::from_request(req),)+),
|
||||
|
@ -933,7 +933,7 @@ impl<P> FromRequest<P> for () {
|
|||
type Error = Error;
|
||||
type Future = FutureResult<(), Error>;
|
||||
|
||||
fn from_request(_req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(_req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<F: Filter + 'static>(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<F: Filter + 'static>(filter: F) -> NotFilter {
|
|||
pub struct NotFilter(Box<Filter>);
|
||||
|
||||
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()
|
||||
|
|
|
@ -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<P>: Sized {
|
|||
type Future: Future<Item = Self, Error = Self::Error>;
|
||||
|
||||
/// Convert request to a Self
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future;
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future;
|
||||
}
|
||||
|
||||
/// Handler converter factory
|
||||
|
@ -306,7 +306,7 @@ impl<P, T: FromRequest<P>> Default for Extract<P, T> {
|
|||
impl<P, T: FromRequest<P>> NewService for Extract<P, T> {
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = (T, HttpRequest);
|
||||
type Error = (Error, ServiceRequest<P>);
|
||||
type Error = (Error, ServiceFromRequest<P>);
|
||||
type InitError = ();
|
||||
type Service = ExtractService<P, T>;
|
||||
type Future = FutureResult<Self::Service, ()>;
|
||||
|
@ -323,14 +323,15 @@ pub struct ExtractService<P, T: FromRequest<P>> {
|
|||
impl<P, T: FromRequest<P>> Service for ExtractService<P, T> {
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = (T, HttpRequest);
|
||||
type Error = (Error, ServiceRequest<P>);
|
||||
type Error = (Error, ServiceFromRequest<P>);
|
||||
type Future = ExtractResponse<P, T>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, mut req: ServiceRequest<P>) -> Self::Future {
|
||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
||||
let mut req = req.into();
|
||||
ExtractResponse {
|
||||
fut: T::from_request(&mut req),
|
||||
req: Some(req),
|
||||
|
@ -339,13 +340,13 @@ impl<P, T: FromRequest<P>> Service for ExtractService<P, T> {
|
|||
}
|
||||
|
||||
pub struct ExtractResponse<P, T: FromRequest<P>> {
|
||||
req: Option<ServiceRequest<P>>,
|
||||
req: Option<ServiceFromRequest<P>>,
|
||||
fut: T::Future,
|
||||
}
|
||||
|
||||
impl<P, T: FromRequest<P>> Future for ExtractResponse<P, T> {
|
||||
type Item = (T, HttpRequest);
|
||||
type Error = (Error, ServiceRequest<P>);
|
||||
type Error = (Error, ServiceFromRequest<P>);
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
let item = try_ready!(self
|
||||
|
|
81
src/lib.rs
81
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<P: 'static>() -> Route<P> {
|
||||
Route::new()
|
||||
}
|
||||
|
||||
pub fn get<P: 'static>() -> Route<P> {
|
||||
Route::get()
|
||||
}
|
||||
|
||||
pub fn post<P: 'static>() -> Route<P> {
|
||||
Route::post()
|
||||
}
|
||||
|
||||
pub fn put<P: 'static>() -> Route<P> {
|
||||
Route::put()
|
||||
}
|
||||
|
||||
pub fn delete<P: 'static>() -> Route<P> {
|
||||
Route::delete()
|
||||
}
|
||||
|
||||
pub fn head<P: 'static>() -> Route<P> {
|
||||
Route::new().method(Method::HEAD)
|
||||
}
|
||||
|
||||
pub fn method<P: 'static>(method: Method) -> Route<P> {
|
||||
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<F, I, R, P: 'static>(handler: F) -> Route<P>
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + '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<Item=HttpResponse, Error=Error> {
|
||||
/// futures::future::ok(HttpResponse::Ok().finish())
|
||||
/// }
|
||||
///
|
||||
/// App::new().resource("/", |r| r.route(web::to_async(index)));
|
||||
/// ```
|
||||
pub fn to_async<F, I, R, P: 'static>(handler: F) -> Route<P>
|
||||
where
|
||||
F: AsyncFactory<I, R>,
|
||||
I: FromRequest<P> + 'static,
|
||||
R: IntoFuture + 'static,
|
||||
R::Item: Into<Response>,
|
||||
R::Error: Into<Error>,
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<RequestHead>,
|
||||
pub(crate) head: Message<RequestHead>,
|
||||
pub(crate) path: Path<Url>,
|
||||
extensions: Rc<Extensions>,
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ impl<P> FromRequest<P> for HttpRequest {
|
|||
type Future = FutureResult<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
ok(req.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
|
||||
|
@ -74,92 +74,8 @@ where
|
|||
/// .finish();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn route<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: FnOnce(RouteBuilder<P>) -> Route<P>,
|
||||
{
|
||||
self.routes.push(f(Route::build()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a new `GET` route.
|
||||
pub fn get<F, I, R>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
self.routes.push(Route::get().to(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a new `POST` route.
|
||||
pub fn post<F, I, R>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
self.routes.push(Route::post().to(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a new `PUT` route.
|
||||
pub fn put<F, I, R>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
self.routes.push(Route::put().to(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a new `DELETE` route.
|
||||
pub fn delete<F, I, R>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
self.routes.push(Route::delete().to(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a new `HEAD` route.
|
||||
pub fn head<F, I, R>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Factory<I, R> + 'static,
|
||||
I: FromRequest<P> + '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<F>(mut self, method: Method, f: F) -> Self
|
||||
where
|
||||
F: FnOnce(RouteBuilder<P>) -> Route<P>,
|
||||
{
|
||||
self.routes.push(f(Route::build().method(method)));
|
||||
pub fn route(mut self, route: Route<P>) -> Self {
|
||||
self.routes.push(route);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -187,7 +103,7 @@ where
|
|||
I: FromRequest<P> + '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<Response>,
|
||||
R::Error: Into<Error>,
|
||||
{
|
||||
self.routes.push(Route::build().to_async(handler));
|
||||
self.routes.push(Route::new().to_async(handler));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
79
src/route.rs
79
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<Req, Res> = Box<
|
||||
Service<
|
||||
|
@ -40,24 +40,29 @@ pub struct Route<P> {
|
|||
}
|
||||
|
||||
impl<P: 'static> Route<P> {
|
||||
pub fn build() -> RouteBuilder<P> {
|
||||
RouteBuilder::new()
|
||||
pub fn new() -> Route<P> {
|
||||
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<P> {
|
||||
RouteBuilder::new().method(Method::GET)
|
||||
pub fn get() -> Route<P> {
|
||||
Route::new().method(Method::GET)
|
||||
}
|
||||
|
||||
pub fn post() -> RouteBuilder<P> {
|
||||
RouteBuilder::new().method(Method::POST)
|
||||
pub fn post() -> Route<P> {
|
||||
Route::new().method(Method::POST)
|
||||
}
|
||||
|
||||
pub fn put() -> RouteBuilder<P> {
|
||||
RouteBuilder::new().method(Method::PUT)
|
||||
pub fn put() -> Route<P> {
|
||||
Route::new().method(Method::PUT)
|
||||
}
|
||||
|
||||
pub fn delete() -> RouteBuilder<P> {
|
||||
RouteBuilder::new().method(Method::DELETE)
|
||||
pub fn delete() -> Route<P> {
|
||||
Route::new().method(Method::DELETE)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +114,7 @@ pub struct RouteService<P> {
|
|||
impl<P> RouteService<P> {
|
||||
pub fn check(&self, req: &mut ServiceRequest<P>) -> bool {
|
||||
for f in self.filters.iter() {
|
||||
if !f.check(req.request()) {
|
||||
if !f.check(req.head()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -132,19 +137,7 @@ impl<P> Service for RouteService<P> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct RouteBuilder<P> {
|
||||
filters: Vec<Box<Filter>>,
|
||||
_t: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<P: 'static> RouteBuilder<P> {
|
||||
fn new() -> RouteBuilder<P> {
|
||||
RouteBuilder {
|
||||
filters: Vec::new(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: 'static> Route<P> {
|
||||
/// Add method match filter to the route.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
|
@ -161,7 +154,9 @@ impl<P: 'static> RouteBuilder<P> {
|
|||
/// # }
|
||||
/// ```
|
||||
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<P: 'static> RouteBuilder<P> {
|
|||
/// # }
|
||||
/// ```
|
||||
pub fn filter<F: Filter + 'static>(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<P: 'static> RouteBuilder<P> {
|
|||
/// ); // <- use `with` extractor
|
||||
/// }
|
||||
/// ```
|
||||
pub fn to<F, T, R>(self, handler: F) -> Route<P>
|
||||
pub fn to<F, T, R>(mut self, handler: F) -> Route<P>
|
||||
where
|
||||
F: Factory<T, R> + 'static,
|
||||
T: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
Route {
|
||||
service: Box::new(RouteNewService::new(
|
||||
self.service = Box::new(RouteNewService::new(
|
||||
Extract::new().and_then(Handle::new(handler).map_err(|_| panic!())),
|
||||
)),
|
||||
filters: Rc::new(self.filters),
|
||||
}
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set async handler function, use request extractor for parameters.
|
||||
|
@ -303,7 +296,7 @@ impl<P: 'static> RouteBuilder<P> {
|
|||
/// }
|
||||
/// ```
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn to_async<F, T, R>(self, handler: F) -> Route<P>
|
||||
pub fn to_async<F, T, R>(mut self, handler: F) -> Self
|
||||
where
|
||||
F: AsyncFactory<T, R>,
|
||||
T: FromRequest<P> + 'static,
|
||||
|
@ -311,12 +304,10 @@ impl<P: 'static> RouteBuilder<P> {
|
|||
R::Item: Into<Response>,
|
||||
R::Error: Into<Error>,
|
||||
{
|
||||
Route {
|
||||
service: Box::new(RouteNewService::new(
|
||||
self.service = Box::new(RouteNewService::new(
|
||||
Extract::new().and_then(AsyncHandle::new(handler).map_err(|_| panic!())),
|
||||
)),
|
||||
filters: Rc::new(self.filters),
|
||||
}
|
||||
));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +441,7 @@ impl<P: 'static> RouteBuilder<P> {
|
|||
|
||||
struct RouteNewService<P, T>
|
||||
where
|
||||
T: NewService<Request = ServiceRequest<P>, Error = (Error, ServiceRequest<P>)>,
|
||||
T: NewService<Request = ServiceRequest<P>, Error = (Error, ServiceFromRequest<P>)>,
|
||||
{
|
||||
service: T,
|
||||
}
|
||||
|
@ -460,7 +451,7 @@ where
|
|||
T: NewService<
|
||||
Request = ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Error = (Error, ServiceRequest<P>),
|
||||
Error = (Error, ServiceFromRequest<P>),
|
||||
>,
|
||||
T::Future: 'static,
|
||||
T::Service: 'static,
|
||||
|
@ -476,7 +467,7 @@ where
|
|||
T: NewService<
|
||||
Request = ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Error = (Error, ServiceRequest<P>),
|
||||
Error = (Error, ServiceFromRequest<P>),
|
||||
>,
|
||||
T::Future: 'static,
|
||||
T::Service: 'static,
|
||||
|
@ -513,7 +504,7 @@ where
|
|||
T: Service<
|
||||
Request = ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Error = (Error, ServiceRequest<P>),
|
||||
Error = (Error, ServiceFromRequest<P>),
|
||||
>,
|
||||
{
|
||||
type Request = ServiceRequest<P>;
|
||||
|
|
151
src/service.rs
151
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<P> ServiceRequest<P> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn request(&self) -> &HttpRequest {
|
||||
&self.req
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_request(self) -> HttpRequest {
|
||||
self.req
|
||||
|
@ -49,10 +46,93 @@ impl<P> ServiceRequest<P> {
|
|||
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<Url> {
|
||||
&self.req.path
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn match_info_mut(&mut self) -> &mut Path<Url> {
|
||||
&mut self.req.path
|
||||
}
|
||||
|
||||
/// Request extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<Extensions> {
|
||||
self.req.head.extensions()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the request's extensions
|
||||
#[inline]
|
||||
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||
self.req.head.extensions_mut()
|
||||
}
|
||||
|
||||
/// Application extensions
|
||||
#[inline]
|
||||
pub fn app_extensions(&self) -> &Extensions {
|
||||
self.req.app_extensions()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> HttpMessage for ServiceRequest<P> {
|
||||
|
@ -70,10 +150,65 @@ impl<P> HttpMessage for ServiceRequest<P> {
|
|||
}
|
||||
|
||||
impl<P> std::ops::Deref for ServiceRequest<P> {
|
||||
type Target = RequestHead;
|
||||
|
||||
fn deref(&self) -> &RequestHead {
|
||||
self.req.head()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> std::ops::DerefMut for ServiceRequest<P> {
|
||||
fn deref_mut(&mut self) -> &mut RequestHead {
|
||||
self.head_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServiceFromRequest<P> {
|
||||
req: HttpRequest,
|
||||
payload: Payload<P>,
|
||||
}
|
||||
|
||||
impl<P> ServiceFromRequest<P> {
|
||||
#[inline]
|
||||
pub fn into_request(self) -> HttpRequest {
|
||||
self.req
|
||||
}
|
||||
|
||||
/// Create service response for error
|
||||
#[inline]
|
||||
pub fn error_response<E: Into<Error>>(self, err: E) -> ServiceResponse {
|
||||
ServiceResponse::new(self.req, err.into().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> std::ops::Deref for ServiceFromRequest<P> {
|
||||
type Target = HttpRequest;
|
||||
|
||||
fn deref(&self) -> &HttpRequest {
|
||||
self.request()
|
||||
&self.req
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> HttpMessage for ServiceFromRequest<P> {
|
||||
type Stream = P;
|
||||
|
||||
#[inline]
|
||||
fn headers(&self) -> &HeaderMap {
|
||||
self.req.headers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn take_payload(&mut self) -> Payload<Self::Stream> {
|
||||
std::mem::replace(&mut self.payload, Payload::None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<ServiceRequest<P>> for ServiceFromRequest<P> {
|
||||
fn from(req: ServiceRequest<P>) -> Self {
|
||||
Self {
|
||||
req: req.req,
|
||||
payload: req.payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<S: 'static, P> FromRequest<P> for State<S> {
|
|||
type Future = FutureResult<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceRequest<P>) -> Self::Future {
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
if let Some(st) = req.app_extensions().get::<State<S>>() {
|
||||
ok(st.clone())
|
||||
} else {
|
||||
|
|
|
@ -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)))),
|
||||
)
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue