1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

Merge branch 'master' into guide

This commit is contained in:
Nikolay Kim 2018-03-28 13:39:59 -07:00 committed by GitHub
commit 5585465859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 3 deletions

View File

@ -26,7 +26,7 @@ pub trait HttpRequestExtractor<T, S>: Sized where T: DeserializeOwned, S: 'stati
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::*;
/// # use actix_web::*;
/// use actix_web::Path;
///
/// /// Application state
@ -113,7 +113,7 @@ impl<T, S> HttpRequestExtractor<T, S> for Path<T, S>
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::*;
/// # use actix_web::*;
/// use actix_web::Query;
///
/// /// Application state
@ -189,6 +189,110 @@ impl<T, S> HttpRequestExtractor<T, S> for Query<T, S>
}
}
/// Extract typed information from from the request's path and query.
///
/// `S` - application state type
///
/// ## Example
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
/// # use actix_web::*;
/// use actix_web::PathAndQuery;
///
/// /// Application state
/// struct State {}
///
/// #[derive(Deserialize)]
/// struct PathParam {
/// username: String,
/// }
///
/// #[derive(Deserialize)]
/// struct QueryParam {
/// count: u32,
/// }
///
/// // use `with` extractor for query info
/// // this handler get called only if request's path contains `username` field
/// // and query contains `count` field
/// fn index(data: PathAndQuery<PathParam, QueryParam, State>) -> Result<String> {
/// Ok(format!("Welcome {}!", data.path().username))
/// }
///
/// fn main() {
/// let app = Application::with_state(State{}).resource(
/// "/index.html",
/// |r| r.method(Method::GET).with(index)); // <- use `with` extractor
/// }
/// ```
pub struct PathAndQuery<P, Q, S=()>{
pitem: P,
qitem: Q,
req: HttpRequest<S>,
}
impl<P, Q, S> PathAndQuery<P, Q, S> {
/// Path information
#[inline]
pub fn path(&self) -> &P {
&self.pitem
}
/// Query information
#[inline]
pub fn query(&self) -> &Q {
&self.qitem
}
/// Shared application state
#[inline]
pub fn state(&self) -> &S {
self.req.state()
}
/// Incoming request
#[inline]
pub fn request(&self) -> &HttpRequest<S> {
&self.req
}
/// Deconstruct instance into a parts
pub fn into(self) -> (P, Q, HttpRequest<S>) {
(self.pitem, self.qitem, self.req)
}
}
impl<T, Q, S> HttpRequestExtractor<T, S> for PathAndQuery<T, Q, S>
where T: de::DeserializeOwned, Q: de::DeserializeOwned, S: 'static
{
type Result = FutureResult<Self, Error>;
#[inline]
fn extract(req: &HttpRequest<S>) -> Self::Result {
let req = req.clone();
let qitem = match serde_urlencoded::from_str::<Q>(req.query_string())
.map_err(|e| e.into())
{
Ok(item) => item,
Err(err) => return result(Err(err))
};
let pitem = match de::Deserialize::deserialize(PathExtractor{req: &req})
.map_err(|e| e.into())
{
Ok(item) => item,
Err(err) => return result(Err(err))
};
result(Ok(PathAndQuery{pitem, qitem, req}))
}
}
macro_rules! unsupported_type {
($trait_fn:ident, $name:expr) => {
fn $trait_fn<V>(self, _: V) -> Result<V::Value, Self::Error>

View File

@ -145,7 +145,7 @@ pub use route::Route;
pub use resource::Resource;
pub use context::HttpContext;
pub use server::HttpServer;
pub use extractor::{Path, Query};
pub use extractor::{Path, PathAndQuery, Query};
// re-exports
pub use http::{Method, StatusCode, Version};