1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-12-01 02:44:37 +01:00

remove Path and Query from public api

This commit is contained in:
Nikolay Kim 2018-03-26 18:18:38 -07:00
parent 052d5f0bc5
commit 8fff2c7595
6 changed files with 84 additions and 28 deletions

View File

@ -2,6 +2,8 @@
## 0.4.11 ## 0.4.11
* Added `HttpReuqest::extract_xxx()`, type safe path/query information extractor.
* Fix long client urls #129 * Fix long client urls #129
* Fix panic on invalid URL characters #130 * Fix panic on invalid URL characters #130

View File

@ -5,7 +5,7 @@ and [`ResponseError` trait](../actix_web/error/trait.ResponseError.html)
for handling handler's errors. for handling handler's errors.
Any error that implements `ResponseError` trait can be returned as error value. Any error that implements `ResponseError` trait can be returned as error value.
*Handler* can return *Result* object, actix by default provides *Handler* can return *Result* object, actix by default provides
`Responder` implementation for compatible result object. Here is implementation `Responder` implementation for compatible result types. Here is implementation
definition: definition:
```rust,ignore ```rust,ignore
@ -64,7 +64,7 @@ fn index(req: HttpRequest) -> Result<&'static str, MyError> {
# } # }
``` ```
In this example *index* handler will always return *500* response. But it is easy In this example *index* handler always returns *500* response. But it is easy
to return different responses for different type of errors. to return different responses for different type of errors.
```rust ```rust
@ -109,7 +109,7 @@ fn index(req: HttpRequest) -> Result<&'static str, MyError> {
## Error helpers ## Error helpers
Actix provides set of error helper types. It is possible to use them to generate Actix provides set of error helper types. It is possible to use them to generate
specific error responses. We can use helper types for first example with custom error. specific error responses. We can use helper types for the first example with custom error.
```rust ```rust
# extern crate actix_web; # extern crate actix_web;

View File

@ -13,6 +13,7 @@ use http2::Error as Http2Error;
use http::{header, StatusCode, Error as HttpError}; use http::{header, StatusCode, Error as HttpError};
use http::uri::InvalidUri; use http::uri::InvalidUri;
use http_range::HttpRangeParseError; use http_range::HttpRangeParseError;
use serde::de::value::Error as DeError;
use serde_json::error::Error as JsonError; use serde_json::error::Error as JsonError;
pub use url::ParseError as UrlParseError; pub use url::ParseError as UrlParseError;
@ -109,6 +110,13 @@ impl ResponseError for JsonError {}
/// `InternalServerError` for `UrlParseError` /// `InternalServerError` for `UrlParseError`
impl ResponseError for UrlParseError {} impl ResponseError for UrlParseError {}
/// Return `BAD_REQUEST` for `de::value::Error`
impl ResponseError for DeError {
fn error_response(&self) -> HttpResponse {
HttpResponse::new(StatusCode::BAD_REQUEST, Body::Empty)
}
}
/// Return `InternalServerError` for `HttpError`, /// Return `InternalServerError` for `HttpError`,
/// Response generation can return `HttpError`, so it is internal error /// Response generation can return `HttpError`, so it is internal error
impl ResponseError for HttpError {} impl ResponseError for HttpError {}

View File

@ -1,11 +1,10 @@
use serde_urlencoded; use serde_urlencoded;
use serde::de::{self, Deserializer, Visitor, Error as DeError}; use serde::de::{self, Deserializer, Visitor, Error as DeError};
use error::{Error, ErrorBadRequest};
use httprequest::HttpRequest; use httprequest::HttpRequest;
pub trait HttpRequestExtractor<'de> { pub trait HttpRequestExtractor<'de> {
fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, Error> fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, de::value::Error>
where T: de::Deserialize<'de>, S: 'static; where T: de::Deserialize<'de>, S: 'static;
} }
@ -19,6 +18,7 @@ pub trait HttpRequestExtractor<'de> {
/// # extern crate futures; /// # extern crate futures;
/// #[macro_use] extern crate serde_derive; /// #[macro_use] extern crate serde_derive;
/// use actix_web::*; /// use actix_web::*;
/// use actix_web::dev::{Path, HttpRequestExtractor};
/// ///
/// #[derive(Deserialize)] /// #[derive(Deserialize)]
/// struct Info { /// struct Info {
@ -26,7 +26,7 @@ pub trait HttpRequestExtractor<'de> {
/// } /// }
/// ///
/// fn index(mut req: HttpRequest) -> Result<String> { /// fn index(mut req: HttpRequest) -> Result<String> {
/// let info: Info = req.extract(Path)?; // <- extract path info using serde /// let info: Info = Path.extract(&req)?; // <- extract path info using serde
/// Ok(format!("Welcome {}!", info.username)) /// Ok(format!("Welcome {}!", info.username))
/// } /// }
/// ///
@ -40,11 +40,10 @@ pub struct Path;
impl<'de> HttpRequestExtractor<'de> for Path { impl<'de> HttpRequestExtractor<'de> for Path {
#[inline] #[inline]
fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, Error> fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, de::value::Error>
where T: de::Deserialize<'de>, S: 'static, where T: de::Deserialize<'de>, S: 'static,
{ {
Ok(de::Deserialize::deserialize(PathExtractor{req: req}) de::Deserialize::deserialize(PathExtractor{req: req})
.map_err(ErrorBadRequest)?)
} }
} }
@ -58,6 +57,7 @@ impl<'de> HttpRequestExtractor<'de> for Path {
/// # extern crate futures; /// # extern crate futures;
/// #[macro_use] extern crate serde_derive; /// #[macro_use] extern crate serde_derive;
/// use actix_web::*; /// use actix_web::*;
/// use actix_web::dev::{Query, HttpRequestExtractor};
/// ///
/// #[derive(Deserialize)] /// #[derive(Deserialize)]
/// struct Info { /// struct Info {
@ -65,7 +65,7 @@ impl<'de> HttpRequestExtractor<'de> for Path {
/// } /// }
/// ///
/// fn index(mut req: HttpRequest) -> Result<String> { /// fn index(mut req: HttpRequest) -> Result<String> {
/// let info: Info = req.extract(Query)?; // <- extract query info using serde /// let info: Info = Query.extract(&req)?; // <- extract query info using serde
/// Ok(format!("Welcome {}!", info.username)) /// Ok(format!("Welcome {}!", info.username))
/// } /// }
/// ///
@ -75,11 +75,10 @@ pub struct Query;
impl<'de> HttpRequestExtractor<'de> for Query { impl<'de> HttpRequestExtractor<'de> for Query {
#[inline] #[inline]
fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, Error> fn extract<T, S>(&self, req: &'de HttpRequest<S>) -> Result<T, de::value::Error>
where T: de::Deserialize<'de>, S: 'static, where T: de::Deserialize<'de>, S: 'static,
{ {
Ok(serde_urlencoded::from_str::<T>(req.query_string()) serde_urlencoded::from_str::<T>(req.query_string())
.map_err(ErrorBadRequest)?)
} }
} }
@ -189,7 +188,6 @@ impl<'de, S: 'static> Deserializer<'de> for PathExtractor<'de, S>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use router::{Router, Pattern}; use router::{Router, Pattern};
use resource::Resource; use resource::Resource;
use test::TestRequest; use test::TestRequest;
@ -217,15 +215,15 @@ mod tests {
let (router, _) = Router::new("", ServerSettings::default(), routes); let (router, _) = Router::new("", ServerSettings::default(), routes);
assert!(router.recognize(&mut req).is_some()); assert!(router.recognize(&mut req).is_some());
let s: MyStruct = req.extract(Path).unwrap(); let s: MyStruct = req.extract_path().unwrap();
assert_eq!(s.key, "name"); assert_eq!(s.key, "name");
assert_eq!(s.value, "user1"); assert_eq!(s.value, "user1");
let s: (String, String) = req.extract(Path).unwrap(); let s: (String, String) = req.extract_path().unwrap();
assert_eq!(s.0, "name"); assert_eq!(s.0, "name");
assert_eq!(s.1, "user1"); assert_eq!(s.1, "user1");
let s: Id = req.extract(Query).unwrap(); let s: Id = req.extract_query().unwrap();
assert_eq!(s.id, "test"); assert_eq!(s.id, "test");
} }
} }

View File

@ -20,7 +20,7 @@ use payload::Payload;
use httpmessage::HttpMessage; use httpmessage::HttpMessage;
use httpresponse::{HttpResponse, HttpResponseBuilder}; use httpresponse::{HttpResponse, HttpResponseBuilder};
use helpers::SharedHttpInnerMessage; use helpers::SharedHttpInnerMessage;
use extractor::HttpRequestExtractor; use extractor::{Path, Query, HttpRequestExtractor};
use error::{Error, UrlGenerationError, CookieParseError, PayloadError}; use error::{Error, UrlGenerationError, CookieParseError, PayloadError};
@ -383,6 +383,7 @@ impl<S> HttpRequest<S> {
} }
/// Get a reference to the Params object. /// Get a reference to the Params object.
///
/// Params is a container for url parameters. /// Params is a container for url parameters.
/// Route supports glob patterns: * for a single wildcard segment and :param /// Route supports glob patterns: * for a single wildcard segment and :param
/// for matching storing that segment of the request url in the Params object. /// for matching storing that segment of the request url in the Params object.
@ -397,14 +398,15 @@ impl<S> HttpRequest<S> {
unsafe{ mem::transmute(&mut self.as_mut().params) } unsafe{ mem::transmute(&mut self.as_mut().params) }
} }
/// Extract typed information from path. /// Extract typed information from request's path.
///
/// By default, in case of error `BAD_REQUEST` response get returned to peer.
/// If you need to return different response use `map_err()` method.
/// ///
/// ## Example /// ## Example
/// ///
/// ```rust /// ```rust
/// # extern crate bytes;
/// # extern crate actix_web; /// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive; /// #[macro_use] extern crate serde_derive;
/// use actix_web::*; /// use actix_web::*;
/// ///
@ -414,8 +416,7 @@ impl<S> HttpRequest<S> {
/// } /// }
/// ///
/// fn index(mut req: HttpRequest) -> Result<String> { /// fn index(mut req: HttpRequest) -> Result<String> {
/// let info: Info = req.extract(Path)?; // <- extract path info using serde /// let info: Info = req.extract_path()?; // <- extract path info using serde
/// let info: Info = req.extract(Query)?; // <- extract query info
/// Ok(format!("Welcome {}!", info.username)) /// Ok(format!("Welcome {}!", info.username))
/// } /// }
/// ///
@ -425,12 +426,60 @@ impl<S> HttpRequest<S> {
/// |r| r.method(Method::GET).f(index)); /// |r| r.method(Method::GET).f(index));
/// } /// }
/// ``` /// ```
pub fn extract<'a, T, D>(&'a self, ds: D) -> Result<T, Error> pub fn extract_path<'a, T>(&'a self) -> Result<T, Error>
where S: 'static, where S: 'static,
T: de::Deserialize<'a>, T: de::Deserialize<'a>,
D: HttpRequestExtractor<'a>
{ {
ds.extract(self) Ok(Path.extract(self)?)
}
/// Extract typed information from request's query string.
///
/// ## Example
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{HttpRequest, Result};
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// fn index(mut req: HttpRequest) -> Result<String> {
/// let info: Info = req.extract_query()?; // <- extract query info, i.e: /?id=username
/// Ok(format!("Welcome {}!", info.username))
/// }
/// # fn main() {}
/// ```
///
/// By default, in case of error, `BAD_REQUEST` response get returned to peer.
/// If you need to return different response use `map_err()` method.
///
/// ```rust
/// # extern crate actix_web;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{HttpRequest, Result, error};
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// fn index(mut req: HttpRequest) -> Result<String> {
/// let info: Info = req.extract_query() // <- extract query information
/// .map_err(error::ErrorInternalServerError)?; // <- return 500 in case of error
/// Ok(format!("Welcome {}!", info.username))
/// }
/// # fn main() {}
/// ```
///
pub fn extract_query<'a, T>(&'a self) -> Result<T, Error>
where S: 'static,
T: de::Deserialize<'a>,
{
Ok(Query.extract(self)?)
} }
/// Checks if a connection should be kept alive. /// Checks if a connection should be kept alive.

View File

@ -144,7 +144,6 @@ pub use route::Route;
pub use resource::Resource; pub use resource::Resource;
pub use context::HttpContext; pub use context::HttpContext;
pub use server::HttpServer; pub use server::HttpServer;
pub use extractor::{Path, Query};
// re-exports // re-exports
pub use http::{Method, StatusCode, Version}; pub use http::{Method, StatusCode, Version};
@ -190,5 +189,5 @@ pub mod dev {
pub use param::{FromParam, Params}; pub use param::{FromParam, Params};
pub use httpmessage::{UrlEncoded, MessageBody}; pub use httpmessage::{UrlEncoded, MessageBody};
pub use httpresponse::HttpResponseBuilder; pub use httpresponse::HttpResponseBuilder;
pub use extractor::HttpRequestExtractor; pub use extractor::{Path, Query, HttpRequestExtractor};
} }