mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 07:53:00 +01:00
added extractor configuration system
This commit is contained in:
parent
08fcb6891e
commit
6df85e32df
@ -23,7 +23,7 @@ use actix_http::http::StatusCode;
|
||||
use actix_http::{HttpMessage, Response};
|
||||
use actix_router::PathDeserializer;
|
||||
|
||||
use crate::handler::FromRequest;
|
||||
use crate::handler::{ConfigStorage, ExtractorConfig, FromRequest};
|
||||
use crate::request::HttpRequest;
|
||||
use crate::responder::Responder;
|
||||
use crate::service::ServiceFromRequest;
|
||||
@ -133,6 +133,7 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self, Error>;
|
||||
type Config = ();
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
@ -219,6 +220,7 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self, Error>;
|
||||
type Config = ();
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
@ -299,16 +301,18 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item = Self, Error = Error>>;
|
||||
type Config = FormConfig;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = FormConfig::default();
|
||||
|
||||
let req2 = req.clone();
|
||||
let cfg = req.load_config::<FormConfig>();
|
||||
|
||||
let limit = cfg.limit;
|
||||
let err = Rc::clone(&cfg.ehandler);
|
||||
Box::new(
|
||||
UrlEncoded::new(req)
|
||||
.limit(cfg.limit)
|
||||
.limit(limit)
|
||||
.map_err(move |e| (*err)(e, &req2))
|
||||
.map(Form),
|
||||
)
|
||||
@ -356,6 +360,7 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct FormConfig {
|
||||
limit: usize,
|
||||
ehandler: Rc<Fn(UrlencodedError, &HttpRequest) -> Error>,
|
||||
@ -363,13 +368,13 @@ pub struct FormConfig {
|
||||
|
||||
impl FormConfig {
|
||||
/// Change max size of payload. By default max size is 256Kb
|
||||
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
||||
pub fn limit(mut self, limit: usize) -> Self {
|
||||
self.limit = limit;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set custom error handler
|
||||
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
||||
pub fn error_handler<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Fn(UrlencodedError, &HttpRequest) -> Error + 'static,
|
||||
{
|
||||
@ -378,6 +383,8 @@ impl FormConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractorConfig for FormConfig {}
|
||||
|
||||
impl Default for FormConfig {
|
||||
fn default() -> Self {
|
||||
FormConfig {
|
||||
@ -509,16 +516,18 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item = Self, Error = Error>>;
|
||||
type Config = JsonConfig;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = JsonConfig::default();
|
||||
|
||||
let req2 = req.clone();
|
||||
let cfg = req.load_config::<JsonConfig>();
|
||||
|
||||
let limit = cfg.limit;
|
||||
let err = Rc::clone(&cfg.ehandler);
|
||||
Box::new(
|
||||
JsonBody::new(req)
|
||||
.limit(cfg.limit)
|
||||
.limit(limit)
|
||||
.map_err(move |e| (*err)(e, &req2))
|
||||
.map(Json),
|
||||
)
|
||||
@ -555,6 +564,7 @@ where
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct JsonConfig {
|
||||
limit: usize,
|
||||
ehandler: Rc<Fn(JsonPayloadError, &HttpRequest) -> Error>,
|
||||
@ -562,13 +572,13 @@ pub struct JsonConfig {
|
||||
|
||||
impl JsonConfig {
|
||||
/// Change max size of payload. By default max size is 256Kb
|
||||
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
||||
pub fn limit(mut self, limit: usize) -> Self {
|
||||
self.limit = limit;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set custom error handler
|
||||
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
||||
pub fn error_handler<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: Fn(JsonPayloadError, &HttpRequest) -> Error + 'static,
|
||||
{
|
||||
@ -577,6 +587,8 @@ impl JsonConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractorConfig for JsonConfig {}
|
||||
|
||||
impl Default for JsonConfig {
|
||||
fn default() -> Self {
|
||||
JsonConfig {
|
||||
@ -617,16 +629,18 @@ where
|
||||
type Error = Error;
|
||||
type Future =
|
||||
Either<Box<Future<Item = Bytes, Error = Error>>, FutureResult<Bytes, Error>>;
|
||||
type Config = PayloadConfig;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = PayloadConfig::default();
|
||||
let cfg = req.load_config::<PayloadConfig>();
|
||||
|
||||
if let Err(e) = cfg.check_mimetype(req) {
|
||||
return Either::B(err(e));
|
||||
}
|
||||
|
||||
Either::A(Box::new(MessageBody::new(req).limit(cfg.limit).from_err()))
|
||||
let limit = cfg.limit;
|
||||
Either::A(Box::new(MessageBody::new(req).limit(limit).from_err()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,10 +678,11 @@ where
|
||||
type Error = Error;
|
||||
type Future =
|
||||
Either<Box<Future<Item = String, Error = Error>>, FutureResult<String, Error>>;
|
||||
type Config = PayloadConfig;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let cfg = PayloadConfig::default();
|
||||
let cfg = req.load_config::<PayloadConfig>();
|
||||
|
||||
// check content-type
|
||||
if let Err(e) = cfg.check_mimetype(req) {
|
||||
@ -679,10 +694,11 @@ where
|
||||
Ok(enc) => enc,
|
||||
Err(e) => return Either::B(err(e.into())),
|
||||
};
|
||||
let limit = cfg.limit;
|
||||
|
||||
Either::A(Box::new(
|
||||
MessageBody::new(req)
|
||||
.limit(cfg.limit)
|
||||
.limit(limit)
|
||||
.from_err()
|
||||
.and_then(move |body| {
|
||||
let enc: *const Encoding = encoding as *const Encoding;
|
||||
@ -753,6 +769,7 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item = Option<T>, Error = Error>>;
|
||||
type Config = T::Config;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
@ -816,6 +833,7 @@ where
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item = Result<T, T::Error>, Error = Error>>;
|
||||
type Config = T::Config;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
@ -827,21 +845,27 @@ where
|
||||
}
|
||||
|
||||
/// Payload configuration for request's payload.
|
||||
#[derive(Clone)]
|
||||
pub struct PayloadConfig {
|
||||
limit: usize,
|
||||
mimetype: Option<Mime>,
|
||||
}
|
||||
|
||||
impl PayloadConfig {
|
||||
/// Create `PayloadConfig` instance and set max size of payload.
|
||||
pub fn new(limit: usize) -> Self {
|
||||
Self::default().limit(limit)
|
||||
}
|
||||
|
||||
/// Change max size of payload. By default max size is 256Kb
|
||||
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
||||
pub fn limit(mut self, limit: usize) -> Self {
|
||||
self.limit = limit;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set required mime-type of the request. By default mime type is not
|
||||
/// enforced.
|
||||
pub fn mimetype(&mut self, mt: Mime) -> &mut Self {
|
||||
pub fn mimetype(mut self, mt: Mime) -> Self {
|
||||
self.mimetype = Some(mt);
|
||||
self
|
||||
}
|
||||
@ -867,6 +891,8 @@ impl PayloadConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractorConfig for PayloadConfig {}
|
||||
|
||||
impl Default for PayloadConfig {
|
||||
fn default() -> Self {
|
||||
PayloadConfig {
|
||||
@ -876,6 +902,16 @@ impl Default for PayloadConfig {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple_config ({ $($T:ident),+} => {
|
||||
impl<$($T,)+> ExtractorConfig for ($($T,)+)
|
||||
where $($T: ExtractorConfig + Clone,)+
|
||||
{
|
||||
fn store_default(ext: &mut ConfigStorage) {
|
||||
$($T::store_default(ext);)+
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
||||
|
||||
/// FromRequest implementation for tuple
|
||||
@ -883,6 +919,7 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = $fut_type<P, $($T),+>;
|
||||
type Config = ($($T::Config,)+);
|
||||
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
$fut_type {
|
||||
@ -932,6 +969,7 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
||||
impl<P> FromRequest<P> for () {
|
||||
type Error = Error;
|
||||
type Future = FutureResult<(), Error>;
|
||||
type Config = ();
|
||||
|
||||
fn from_request(_req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
ok(())
|
||||
@ -942,6 +980,17 @@ impl<P> FromRequest<P> for () {
|
||||
mod m {
|
||||
use super::*;
|
||||
|
||||
tuple_config!(A);
|
||||
tuple_config!(A, B);
|
||||
tuple_config!(A, B, C);
|
||||
tuple_config!(A, B, C, D);
|
||||
tuple_config!(A, B, C, D, E);
|
||||
tuple_config!(A, B, C, D, E, F);
|
||||
tuple_config!(A, B, C, D, E, F, G);
|
||||
tuple_config!(A, B, C, D, E, F, G, H);
|
||||
tuple_config!(A, B, C, D, E, F, G, H, I);
|
||||
tuple_config!(A, B, C, D, E, F, G, H, I, J);
|
||||
|
||||
tuple_from_req!(TupleFromRequest1, (0, A));
|
||||
tuple_from_req!(TupleFromRequest2, (0, A), (1, B));
|
||||
tuple_from_req!(TupleFromRequest3, (0, A), (1, B), (2, C));
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
|
||||
use actix_http::{Error, Response};
|
||||
use actix_http::{Error, Extensions, Response};
|
||||
use actix_service::{NewService, Service, Void};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{try_ready, Async, Future, IntoFuture, Poll};
|
||||
@ -19,10 +21,41 @@ pub trait FromRequest<P>: Sized {
|
||||
/// Future that resolves to a Self
|
||||
type Future: Future<Item = Self, Error = Self::Error>;
|
||||
|
||||
/// Configuration for the extractor
|
||||
type Config: ExtractorConfig;
|
||||
|
||||
/// Convert request to a Self
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future;
|
||||
}
|
||||
|
||||
/// Storage for extractor configs
|
||||
#[derive(Default)]
|
||||
pub struct ConfigStorage {
|
||||
pub(crate) storage: Option<Rc<Extensions>>,
|
||||
}
|
||||
|
||||
impl ConfigStorage {
|
||||
pub fn store<C: ExtractorConfig>(&mut self, config: C) {
|
||||
if self.storage.is_none() {
|
||||
self.storage = Some(Rc::new(Extensions::new()));
|
||||
}
|
||||
if let Some(ref mut ext) = self.storage {
|
||||
Rc::get_mut(ext).unwrap().insert(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExtractorConfig: Default + Clone + 'static {
|
||||
/// Set default configuration to config storage
|
||||
fn store_default(ext: &mut ConfigStorage) {
|
||||
ext.store(Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractorConfig for () {
|
||||
fn store_default(_: &mut ConfigStorage) {}
|
||||
}
|
||||
|
||||
/// Handler converter factory
|
||||
pub trait Factory<T, R>: Clone
|
||||
where
|
||||
@ -288,19 +321,17 @@ where
|
||||
|
||||
/// Extract arguments from request
|
||||
pub struct Extract<P, T: FromRequest<P>> {
|
||||
config: Rc<RefCell<Option<Rc<Extensions>>>>,
|
||||
_t: PhantomData<(P, T)>,
|
||||
}
|
||||
|
||||
impl<P, T: FromRequest<P>> Extract<P, T> {
|
||||
pub fn new() -> Self {
|
||||
Extract { _t: PhantomData }
|
||||
pub fn new(config: Rc<RefCell<Option<Rc<Extensions>>>>) -> Self {
|
||||
Extract {
|
||||
config,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, T: FromRequest<P>> Default for Extract<P, T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, T: FromRequest<P>> NewService for Extract<P, T> {
|
||||
@ -312,11 +343,15 @@ impl<P, T: FromRequest<P>> NewService for Extract<P, T> {
|
||||
type Future = FutureResult<Self::Service, ()>;
|
||||
|
||||
fn new_service(&self, _: &()) -> Self::Future {
|
||||
ok(ExtractService { _t: PhantomData })
|
||||
ok(ExtractService {
|
||||
_t: PhantomData,
|
||||
config: self.config.borrow().clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExtractService<P, T: FromRequest<P>> {
|
||||
config: Option<Rc<Extensions>>,
|
||||
_t: PhantomData<(P, T)>,
|
||||
}
|
||||
|
||||
@ -331,7 +366,7 @@ impl<P, T: FromRequest<P>> Service for ExtractService<P, T> {
|
||||
}
|
||||
|
||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
||||
let mut req = req.into();
|
||||
let mut req = ServiceFromRequest::new(req, self.config.clone());
|
||||
ExtractResponse {
|
||||
fut: T::from_request(&mut req),
|
||||
req: Some(req),
|
||||
@ -365,7 +400,6 @@ impl<P, T: FromRequest<P>> Future for ExtractResponse<P, T> {
|
||||
macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => {
|
||||
impl<Func, $($T,)+ Res> Factory<($($T,)+), Res> for Func
|
||||
where Func: Fn($($T,)+) -> Res + Clone + 'static,
|
||||
//$($T,)+
|
||||
Res: Responder + 'static,
|
||||
{
|
||||
fn call(&self, param: ($($T,)+)) -> Res {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
mod app;
|
||||
mod extractor;
|
||||
pub mod extractor;
|
||||
pub mod handler;
|
||||
// mod info;
|
||||
pub mod blocking;
|
||||
@ -20,7 +20,7 @@ pub use actix_http::Response as HttpResponse;
|
||||
pub use actix_http::{http, Error, HttpMessage, ResponseError};
|
||||
|
||||
pub use crate::app::App;
|
||||
pub use crate::extractor::{Form, Json, Path, Query};
|
||||
pub use crate::extractor::{Form, Json, Path, PayloadConfig, Query};
|
||||
pub use crate::handler::FromRequest;
|
||||
pub use crate::request::HttpRequest;
|
||||
pub use crate::resource::Resource;
|
||||
|
@ -143,6 +143,7 @@ impl HttpMessage for HttpRequest {
|
||||
impl<P> FromRequest<P> for HttpRequest {
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self, Error>;
|
||||
type Config = ();
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
|
@ -75,7 +75,7 @@ where
|
||||
/// }
|
||||
/// ```
|
||||
pub fn route(mut self, route: Route<P>) -> Self {
|
||||
self.routes.push(route);
|
||||
self.routes.push(route.finish());
|
||||
self
|
||||
}
|
||||
|
||||
|
64
src/route.rs
64
src/route.rs
@ -1,11 +1,15 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use actix_http::{http::Method, Error, Response};
|
||||
use actix_http::{http::Method, Error, Extensions, Response};
|
||||
use actix_service::{NewService, Service};
|
||||
use futures::{Async, Future, IntoFuture, Poll};
|
||||
|
||||
use crate::filter::{self, Filter};
|
||||
use crate::handler::{AsyncFactory, AsyncHandle, Extract, Factory, FromRequest, Handle};
|
||||
use crate::handler::{
|
||||
AsyncFactory, AsyncHandle, ConfigStorage, Extract, ExtractorConfig, Factory,
|
||||
FromRequest, Handle,
|
||||
};
|
||||
use crate::responder::Responder;
|
||||
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||
use crate::HttpResponse;
|
||||
@ -37,33 +41,50 @@ type BoxedRouteNewService<Req, Res> = Box<
|
||||
pub struct Route<P> {
|
||||
service: BoxedRouteNewService<ServiceRequest<P>, ServiceResponse>,
|
||||
filters: Rc<Vec<Box<Filter>>>,
|
||||
config: ConfigStorage,
|
||||
config_ref: Rc<RefCell<Option<Rc<Extensions>>>>,
|
||||
}
|
||||
|
||||
impl<P: 'static> Route<P> {
|
||||
/// Create new route which matches any request.
|
||||
pub fn new() -> Route<P> {
|
||||
let config_ref = Rc::new(RefCell::new(None));
|
||||
Route {
|
||||
service: Box::new(RouteNewService::new(Extract::new().and_then(
|
||||
service: Box::new(RouteNewService::new(
|
||||
Extract::new(config_ref.clone()).and_then(
|
||||
Handle::new(|| HttpResponse::NotFound()).map_err(|_| panic!()),
|
||||
))),
|
||||
),
|
||||
)),
|
||||
filters: Rc::new(Vec::new()),
|
||||
config: ConfigStorage::default(),
|
||||
config_ref,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new `GET` route.
|
||||
pub fn get() -> Route<P> {
|
||||
Route::new().method(Method::GET)
|
||||
}
|
||||
|
||||
/// Create new `POST` route.
|
||||
pub fn post() -> Route<P> {
|
||||
Route::new().method(Method::POST)
|
||||
}
|
||||
|
||||
/// Create new `PUT` route.
|
||||
pub fn put() -> Route<P> {
|
||||
Route::new().method(Method::PUT)
|
||||
}
|
||||
|
||||
/// Create new `DELETE` route.
|
||||
pub fn delete() -> Route<P> {
|
||||
Route::new().method(Method::DELETE)
|
||||
}
|
||||
|
||||
pub(crate) fn finish(self) -> Self {
|
||||
*self.config_ref.borrow_mut() = self.config.storage.clone();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> NewService for Route<P> {
|
||||
@ -260,8 +281,10 @@ impl<P: 'static> Route<P> {
|
||||
T: FromRequest<P> + 'static,
|
||||
R: Responder + 'static,
|
||||
{
|
||||
T::Config::store_default(&mut self.config);
|
||||
self.service = Box::new(RouteNewService::new(
|
||||
Extract::new().and_then(Handle::new(handler).map_err(|_| panic!())),
|
||||
Extract::new(self.config_ref.clone())
|
||||
.and_then(Handle::new(handler).map_err(|_| panic!())),
|
||||
));
|
||||
self
|
||||
}
|
||||
@ -305,10 +328,39 @@ impl<P: 'static> Route<P> {
|
||||
R::Error: Into<Error>,
|
||||
{
|
||||
self.service = Box::new(RouteNewService::new(
|
||||
Extract::new().and_then(AsyncHandle::new(handler).map_err(|_| panic!())),
|
||||
Extract::new(self.config_ref.clone())
|
||||
.and_then(AsyncHandle::new(handler).map_err(|_| panic!())),
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
/// This method allows to add extractor configuration
|
||||
/// for specific route.
|
||||
///
|
||||
/// ```rust
|
||||
/// use actix_web::{web, extractor, App};
|
||||
///
|
||||
/// /// extract text data from request
|
||||
/// fn index(body: String) -> String {
|
||||
/// format!("Body {}!", body)
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = App::new().resource("/index.html", |r| {
|
||||
/// r.route(
|
||||
/// web::get()
|
||||
/// // limit size of the payload
|
||||
/// .config(extractor::PayloadConfig::new(4096))
|
||||
/// // register handler
|
||||
/// .to(index)
|
||||
/// )
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
pub fn config<C: ExtractorConfig>(mut self, config: C) -> Self {
|
||||
self.config.store(config);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// pub struct RouteServiceBuilder<P, T, U1, U2> {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -167,9 +168,18 @@ impl<P> std::ops::DerefMut for ServiceRequest<P> {
|
||||
pub struct ServiceFromRequest<P> {
|
||||
req: HttpRequest,
|
||||
payload: Payload<P>,
|
||||
config: Option<Rc<Extensions>>,
|
||||
}
|
||||
|
||||
impl<P> ServiceFromRequest<P> {
|
||||
pub(crate) fn new(req: ServiceRequest<P>, config: Option<Rc<Extensions>>) -> Self {
|
||||
Self {
|
||||
req: req.req,
|
||||
payload: req.payload,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_request(self) -> HttpRequest {
|
||||
self.req
|
||||
@ -180,6 +190,16 @@ impl<P> ServiceFromRequest<P> {
|
||||
pub fn error_response<E: Into<Error>>(self, err: E) -> ServiceResponse {
|
||||
ServiceResponse::new(self.req, err.into().into())
|
||||
}
|
||||
|
||||
/// Load extractor configuration
|
||||
pub fn load_config<T: Clone + Default + 'static>(&self) -> Cow<T> {
|
||||
if let Some(ref ext) = self.config {
|
||||
if let Some(cfg) = ext.get::<T>() {
|
||||
return Cow::Borrowed(cfg);
|
||||
}
|
||||
}
|
||||
Cow::Owned(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> std::ops::Deref for ServiceFromRequest<P> {
|
||||
@ -204,15 +224,6 @@ impl<P> HttpMessage for ServiceFromRequest<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<ServiceRequest<P>> for ServiceFromRequest<P> {
|
||||
fn from(req: ServiceRequest<P>) -> Self {
|
||||
Self {
|
||||
req: req.req,
|
||||
payload: req.payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServiceResponse<B = Body> {
|
||||
request: HttpRequest,
|
||||
response: Response<B>,
|
||||
|
@ -48,6 +48,7 @@ impl<S> Clone for State<S> {
|
||||
impl<S: 'static, P> FromRequest<P> for State<S> {
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self, Error>;
|
||||
type Config = ();
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
|
16
src/test.rs
16
src/test.rs
@ -9,7 +9,7 @@ use actix_router::{Path, Url};
|
||||
use bytes::Bytes;
|
||||
|
||||
use crate::request::HttpRequest;
|
||||
use crate::service::ServiceRequest;
|
||||
use crate::service::{ServiceFromRequest, ServiceRequest};
|
||||
|
||||
/// Test `Request` builder
|
||||
///
|
||||
@ -133,7 +133,7 @@ impl TestRequest {
|
||||
}
|
||||
|
||||
/// Complete request creation and generate `HttpRequest` instance
|
||||
pub fn request(mut self) -> HttpRequest {
|
||||
pub fn to_request(mut self) -> HttpRequest {
|
||||
let req = self.req.finish();
|
||||
|
||||
ServiceRequest::new(
|
||||
@ -143,4 +143,16 @@ impl TestRequest {
|
||||
)
|
||||
.into_request()
|
||||
}
|
||||
|
||||
/// Complete request creation and generate `ServiceFromRequest` instance
|
||||
pub fn to_from(mut self) -> ServiceFromRequest<PayloadStream> {
|
||||
let req = self.req.finish();
|
||||
|
||||
let req = ServiceRequest::new(
|
||||
Path::new(Url::new(req.uri().clone())),
|
||||
req,
|
||||
Rc::new(self.extensions),
|
||||
);
|
||||
ServiceFromRequest::new(req, None)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user