mirror of
https://github.com/actix/actix-web.git
synced 2024-12-23 08:36:34 +00:00
add Item and Error to FromRequest trait
This commit is contained in:
parent
6bc7d60f52
commit
7c6faaa8e0
14 changed files with 178 additions and 108 deletions
|
@ -109,7 +109,7 @@ fn main() {
|
||||||
Application::default("/")
|
Application::default("/")
|
||||||
.middleware(middlewares::Logger::default()) // <- register logger middleware
|
.middleware(middlewares::Logger::default()) // <- register logger middleware
|
||||||
.resource("/ws/", |r| r.get(|req| ws::start(req, MyWebSocket))) // <- websocket route
|
.resource("/ws/", |r| r.get(|req| ws::start(req, MyWebSocket))) // <- websocket route
|
||||||
.route("/", StaticFiles::new("examples/static/", true))) // <- server static files
|
.route("/", fs::StaticFiles::new("examples/static/", true))) // <- serve static files
|
||||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
Arbiter::system().send(msgs::SystemExit(0));
|
Arbiter::system().send(msgs::SystemExit(0));
|
||||||
|
|
10
build.rs
10
build.rs
|
@ -12,8 +12,18 @@ fn main() {
|
||||||
// generates doc tests for `README.md`.
|
// generates doc tests for `README.md`.
|
||||||
skeptic::generate_doc_tests(
|
skeptic::generate_doc_tests(
|
||||||
&["README.md",
|
&["README.md",
|
||||||
|
"guide/src/qs_1.md",
|
||||||
"guide/src/qs_2.md",
|
"guide/src/qs_2.md",
|
||||||
"guide/src/qs_3.md",
|
"guide/src/qs_3.md",
|
||||||
|
"guide/src/qs_4.md",
|
||||||
|
"guide/src/qs_5.md",
|
||||||
|
"guide/src/qs_6.md",
|
||||||
|
"guide/src/qs_7.md",
|
||||||
|
"guide/src/qs_9.md",
|
||||||
|
"guide/src/qs_10.md",
|
||||||
|
"guide/src/qs_11.md",
|
||||||
|
"guide/src/qs_12.md",
|
||||||
|
"guide/src/qs_13.md",
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
let _ = fs::File::create(f);
|
let _ = fs::File::create(f);
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// static files
|
// static files
|
||||||
.route("/static", StaticFiles::new("examples/static/", true)))
|
.route("/static", fs::StaticFiles::new("examples/static/", true)))
|
||||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
println!("Started http server: 127.0.0.1:8080");
|
println!("Started http server: 127.0.0.1:8080");
|
||||||
|
|
|
@ -208,7 +208,7 @@ fn main() {
|
||||||
// websocket
|
// websocket
|
||||||
.resource("/ws/", |r| r.get(chat_route))
|
.resource("/ws/", |r| r.get(chat_route))
|
||||||
// static resources
|
// static resources
|
||||||
.route("/static", StaticFiles::new("static/", true)))
|
.route("/static", fs::StaticFiles::new("static/", true)))
|
||||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
let _ = sys.run();
|
let _ = sys.run();
|
||||||
|
|
|
@ -67,7 +67,7 @@ fn main() {
|
||||||
// websocket route
|
// websocket route
|
||||||
.resource("/ws/", |r| r.get(ws_index))
|
.resource("/ws/", |r| r.get(ws_index))
|
||||||
// static files
|
// static files
|
||||||
.route("/", StaticFiles::new("examples/static/", true)))
|
.route("/", fs::StaticFiles::new("examples/static/", true)))
|
||||||
// start http server on 127.0.0.1:8080
|
// start http server on 127.0.0.1:8080
|
||||||
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@ A request handler can by any object that implements
|
||||||
By default actix provdes several `Handler` implementations:
|
By default actix provdes several `Handler` implementations:
|
||||||
|
|
||||||
* Simple function that accepts `HttpRequest` and returns any object that
|
* Simple function that accepts `HttpRequest` and returns any object that
|
||||||
can be converted to `HttpResponse`
|
implements `FromRequest` trait
|
||||||
* Function that accepts `HttpRequest` and returns `Result<Reply, Into<Error>>` object.
|
* Function that accepts `HttpRequest` and returns `Result<Reply, Into<Error>>` object.
|
||||||
* Function that accepts `HttpRequest` and return actor that has `HttpContext<A>`as a context.
|
* Function that accepts `HttpRequest` and return actor that has `HttpContext<A>`as a context.
|
||||||
|
|
||||||
Actix provides response conversion into `HttpResponse` for some standard types,
|
Actix provides response `FromRequest` implementation for some standard types,
|
||||||
like `&'static str`, `String`, etc.
|
like `&'static str`, `String`, etc.
|
||||||
For complete list of implementations check
|
For complete list of implementations check
|
||||||
[HttpResponse documentation](../actix_web/struct.HttpResponse.html#implementations).
|
[FromRequest documentation](../actix_web/trait.FromRequest.html#foreign-impls).
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
@ -58,19 +58,18 @@ struct MyObj {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// we have to convert Error into HttpResponse as well, but with
|
/// we have to convert Error into HttpResponse as well
|
||||||
/// specialization this could be handled genericly.
|
impl FromRequest for MyObj {
|
||||||
impl Into<HttpResponse> for MyObj {
|
type Item = HttpResponse;
|
||||||
fn into(self) -> HttpResponse {
|
type Error = Error;
|
||||||
let body = match serde_json::to_string(&self) {
|
|
||||||
Err(err) => return Error::from(err).into(),
|
fn from_request(self, req: HttpRequest) -> Result<HttpResponse> {
|
||||||
Ok(body) => body,
|
let body = serde_json::to_string(&self)?;
|
||||||
};
|
|
||||||
|
|
||||||
// Create response and set content type
|
// Create response and set content type
|
||||||
HttpResponse::Ok()
|
Ok(HttpResponse::Ok()
|
||||||
.content_type("application/json")
|
.content_type("application/json")
|
||||||
.body(body).unwrap()
|
.body(body)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,20 +89,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If `specialization` is enabled, conversion could be simplier:
|
|
||||||
|
|
||||||
```rust,ignore
|
|
||||||
impl Into<Result<HttpResponse>> for MyObj {
|
|
||||||
fn into(self) -> Result<HttpResponse> {
|
|
||||||
let body = serde_json::to_string(&self)?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok()
|
|
||||||
.content_type("application/json")
|
|
||||||
.body(body)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Async handlers
|
## Async handlers
|
||||||
|
|
||||||
There are two different types of async handlers.
|
There are two different types of async handlers.
|
||||||
|
|
|
@ -65,11 +65,11 @@ used later in a request handler to access the matched value for that part. This
|
||||||
done by looking up the identifier in the `HttpRequest.match_info` object:
|
done by looking up the identifier in the `HttpRequest.match_info` object:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate actix;
|
extern crate actix_web;
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
|
||||||
fn index(req: Httprequest) -> String {
|
fn index(req: HttpRequest) -> String {
|
||||||
format!("Hello, {}", req.match_info["name"])
|
format!("Hello, {}", &req.match_info()["name"])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -96,13 +96,13 @@ implements `FromParam` trait. For example most of standard integer types
|
||||||
implements `FromParam` trait. i.e.:
|
implements `FromParam` trait. i.e.:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate actix;
|
extern crate actix_web;
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
|
||||||
fn index(req: Httprequest) -> String {
|
fn index(req: HttpRequest) -> Result<String> {
|
||||||
let v1: u8 = req.match_info().query("v1")?;
|
let v1: u8 = req.match_info().query("v1")?;
|
||||||
let v2: u8 = req.match_info().query("v2")?;
|
let v2: u8 = req.match_info().query("v2")?;
|
||||||
format!("Values {} {}", v1, v2)
|
Ok(format!("Values {} {}", v1, v2))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -146,18 +146,18 @@ safe to interpolate within, or use as a suffix of, a path without additional
|
||||||
checks.
|
checks.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate actix;
|
extern crate actix_web;
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
fn index(req: Httprequest) -> String {
|
fn index(req: HttpRequest) -> Result<String> {
|
||||||
let path: PathBuf = req.match_info().query("tail")?;
|
let path: PathBuf = req.match_info().query("tail")?;
|
||||||
format!("Path {:?}", path)
|
Ok(format!("Path {:?}", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Application::default("/")
|
Application::default("/")
|
||||||
.resource(r"/a/{tail:**}", |r| r.get(index))
|
.resource(r"/a/{tail:*}", |r| r.get(index))
|
||||||
.finish();
|
.finish();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
// dev specific
|
// dev specific
|
||||||
|
pub use route::Handler;
|
||||||
pub use pipeline::Pipeline;
|
pub use pipeline::Pipeline;
|
||||||
pub use route::{Handler, FromRequest};
|
|
||||||
pub use channel::{HttpChannel, HttpHandler};
|
pub use channel::{HttpChannel, HttpHandler};
|
||||||
pub use recognizer::{FromParam, RouteRecognizer};
|
pub use recognizer::{FromParam, RouteRecognizer};
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use httpcodes::{HTTPBadRequest, HTTPMethodNotAllowed, HTTPExpectationFailed};
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
/// General purpose actix web error
|
/// General purpose actix web error
|
||||||
#[derive(Debug)]
|
#[derive(Fail, Debug)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
cause: Box<ResponseError>,
|
cause: Box<ResponseError>,
|
||||||
}
|
}
|
||||||
|
|
10
src/fs.rs
10
src/fs.rs
|
@ -1,6 +1,6 @@
|
||||||
//! Static files support.
|
//! Static files support.
|
||||||
//!
|
|
||||||
//! TODO: needs to re-implement actual files handling, current impl blocks
|
// //! TODO: needs to re-implement actual files handling, current impl blocks
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -19,11 +19,10 @@ use httpcodes::{HTTPOk, HTTPNotFound};
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate actix_web;
|
/// extern crate actix_web;
|
||||||
/// use actix_web::*;
|
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = Application::default("/")
|
/// let app = actix_web::Application::default("/")
|
||||||
/// .route("/static", StaticFiles::new(".", true))
|
/// .route("/static", actix_web::fs::StaticFiles::new(".", true))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -39,6 +38,7 @@ impl StaticFiles {
|
||||||
/// Create new `StaticFiles` instance
|
/// Create new `StaticFiles` instance
|
||||||
///
|
///
|
||||||
/// `dir` - base directory
|
/// `dir` - base directory
|
||||||
|
///
|
||||||
/// `index` - show index for directory
|
/// `index` - show index for directory
|
||||||
pub fn new<D: Into<PathBuf>>(dir: D, index: bool) -> StaticFiles {
|
pub fn new<D: Into<PathBuf>>(dir: D, index: bool) -> StaticFiles {
|
||||||
let dir = dir.into();
|
let dir = dir.into();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Basic http responses
|
//! Basic http responses
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
use http::StatusCode;
|
use http::{StatusCode, Error as HttpError};
|
||||||
|
|
||||||
use body::Body;
|
use body::Body;
|
||||||
use route::{Reply, RouteHandler, FromRequest};
|
use route::{Reply, RouteHandler, FromRequest};
|
||||||
|
@ -74,8 +74,11 @@ impl<S> RouteHandler<S> for StaticResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for StaticResponse {
|
impl FromRequest for StaticResponse {
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
Reply::response(HttpResponse::new(self.0, Body::Empty))
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
|
self.build().body(Body::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,10 @@ use http::{StatusCode, Version, HeaderMap, HttpTryFrom, Error as HttpError};
|
||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use Cookie;
|
use Cookie;
|
||||||
use body::Body;
|
use body::Body;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use route::{Reply, FromRequest};
|
use route::FromRequest;
|
||||||
use encoding::ContentEncoding;
|
use encoding::ContentEncoding;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
|
|
||||||
|
@ -461,8 +460,11 @@ impl From<HttpResponseBuilder> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for HttpResponseBuilder {
|
impl FromRequest for HttpResponseBuilder {
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
Reply::response(self)
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(mut self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
|
self.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,11 +478,13 @@ impl From<&'static str> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for &'static str {
|
impl FromRequest for &'static str {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("text/plain; charset=utf-8")
|
.content_type("text/plain; charset=utf-8")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,11 +498,13 @@ impl From<&'static [u8]> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for &'static [u8] {
|
impl FromRequest for &'static [u8] {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("application/octet-stream")
|
.content_type("application/octet-stream")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,11 +518,13 @@ impl From<String> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for String {
|
impl FromRequest for String {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("text/plain; charset=utf-8")
|
.content_type("text/plain; charset=utf-8")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,11 +538,13 @@ impl<'a> From<&'a String> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromRequest for &'a String {
|
impl<'a> FromRequest for &'a String {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("text/plain; charset=utf-8")
|
.content_type("text/plain; charset=utf-8")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,11 +558,13 @@ impl From<Bytes> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for Bytes {
|
impl FromRequest for Bytes {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("application/octet-stream")
|
.content_type("application/octet-stream")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,11 +578,13 @@ impl From<BytesMut> for HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for BytesMut {
|
impl FromRequest for BytesMut {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Item = HttpResponse;
|
||||||
|
type Error = HttpError;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
HttpResponse::build(StatusCode::OK)
|
HttpResponse::build(StatusCode::OK)
|
||||||
.content_type("application/octet-stream")
|
.content_type("application/octet-stream")
|
||||||
.body(self)
|
.body(self)
|
||||||
.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,6 +664,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_response() {
|
fn test_into_response() {
|
||||||
|
let req = HttpRequest::default();
|
||||||
|
|
||||||
let resp: HttpResponse = "test".into();
|
let resp: HttpResponse = "test".into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
@ -657,6 +673,13 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test"));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test"));
|
||||||
|
|
||||||
|
let resp: HttpResponse = "test".from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("text/plain; charset=utf-8"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test"));
|
||||||
|
|
||||||
let resp: HttpResponse = b"test".as_ref().into();
|
let resp: HttpResponse = b"test".as_ref().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
@ -664,6 +687,13 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref()));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref()));
|
||||||
|
|
||||||
|
let resp: HttpResponse = b"test".as_ref().from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("application/octet-stream"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref()));
|
||||||
|
|
||||||
let resp: HttpResponse = "test".to_owned().into();
|
let resp: HttpResponse = "test".to_owned().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
@ -671,6 +701,13 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned()));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned()));
|
||||||
|
|
||||||
|
let resp: HttpResponse = "test".to_owned().from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("text/plain; charset=utf-8"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned()));
|
||||||
|
|
||||||
let resp: HttpResponse = (&"test".to_owned()).into();
|
let resp: HttpResponse = (&"test".to_owned()).into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
@ -678,6 +715,13 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from((&"test".to_owned())));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from((&"test".to_owned())));
|
||||||
|
|
||||||
|
let resp: HttpResponse = (&"test".to_owned()).from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("text/plain; charset=utf-8"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from((&"test".to_owned())));
|
||||||
|
|
||||||
let b = Bytes::from_static(b"test");
|
let b = Bytes::from_static(b"test");
|
||||||
let resp: HttpResponse = b.into();
|
let resp: HttpResponse = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
@ -686,6 +730,14 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from(Bytes::from_static(b"test")));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(Bytes::from_static(b"test")));
|
||||||
|
|
||||||
|
let b = Bytes::from_static(b"test");
|
||||||
|
let resp: HttpResponse = b.from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("application/octet-stream"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(Bytes::from_static(b"test")));
|
||||||
|
|
||||||
let b = BytesMut::from("test");
|
let b = BytesMut::from("test");
|
||||||
let resp: HttpResponse = b.into();
|
let resp: HttpResponse = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
@ -693,5 +745,13 @@ mod tests {
|
||||||
header::HeaderValue::from_static("application/octet-stream"));
|
header::HeaderValue::from_static("application/octet-stream"));
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test")));
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test")));
|
||||||
|
|
||||||
|
let b = BytesMut::from("test");
|
||||||
|
let resp: HttpResponse = b.from_request(req.clone()).ok().unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("application/octet-stream"));
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,6 @@ mod resource;
|
||||||
mod recognizer;
|
mod recognizer;
|
||||||
mod route;
|
mod route;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod fs;
|
|
||||||
mod server;
|
mod server;
|
||||||
mod channel;
|
mod channel;
|
||||||
mod wsframe;
|
mod wsframe;
|
||||||
|
@ -68,6 +67,7 @@ mod h2;
|
||||||
mod h1writer;
|
mod h1writer;
|
||||||
mod h2writer;
|
mod h2writer;
|
||||||
|
|
||||||
|
pub mod fs;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
pub mod dev;
|
pub mod dev;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -81,12 +81,11 @@ pub use application::Application;
|
||||||
pub use httprequest::{HttpRequest, UrlEncoded};
|
pub use httprequest::{HttpRequest, UrlEncoded};
|
||||||
pub use httpresponse::HttpResponse;
|
pub use httpresponse::HttpResponse;
|
||||||
pub use payload::{Payload, PayloadItem};
|
pub use payload::{Payload, PayloadItem};
|
||||||
pub use route::Reply;
|
pub use route::{Reply, FromRequest};
|
||||||
pub use resource::Resource;
|
pub use resource::Resource;
|
||||||
pub use recognizer::Params;
|
pub use recognizer::Params;
|
||||||
pub use server::HttpServer;
|
pub use server::HttpServer;
|
||||||
pub use context::HttpContext;
|
pub use context::HttpContext;
|
||||||
pub use fs::StaticFiles;
|
|
||||||
|
|
||||||
// re-exports
|
// re-exports
|
||||||
pub use http::{Method, StatusCode, Version};
|
pub use http::{Method, StatusCode, Version};
|
||||||
|
|
89
src/route.rs
89
src/route.rs
|
@ -1,5 +1,4 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::result::Result as StdResult;
|
|
||||||
|
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
@ -21,7 +20,13 @@ pub trait Handler<S>: 'static {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromRequest {
|
pub trait FromRequest {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply;
|
/// The associated item which can be returned.
|
||||||
|
type Item: Into<Reply>;
|
||||||
|
|
||||||
|
/// The associated error which can be returned.
|
||||||
|
type Error: Into<Error>;
|
||||||
|
|
||||||
|
fn from_request(self, req: HttpRequest) -> Result<Self::Item, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler<S> for Fn()
|
/// Handler<S> for Fn()
|
||||||
|
@ -72,46 +77,53 @@ impl Reply {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for Reply {
|
impl FromRequest for Reply {
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = Reply;
|
||||||
self
|
type Error = Error;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRequest for HttpResponse {
|
impl FromRequest for HttpResponse {
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = Reply;
|
||||||
Reply(ReplyItem::Message(self))
|
type Error = Error;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
|
Ok(Reply(ReplyItem::Message(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(actix_nightly)]
|
impl From<HttpResponse> for Reply {
|
||||||
default impl<T: FromRequest> FromRequest for T
|
|
||||||
{
|
fn from(resp: HttpResponse) -> Reply {
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
Reply(ReplyItem::Message(resp))
|
||||||
self.from_request(req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(actix_nightly)]
|
impl<T: Into<HttpResponse>, E: Into<Error>> FromRequest for Result<T, E> {
|
||||||
default impl<T: Into<HttpResponse>, E: Into<Error>> FromRequest for StdResult<T, E> {
|
type Item = Reply;
|
||||||
fn from_request(self, req: HttpRequest) -> Reply {
|
type Error = E;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<Reply, Self::Error> {
|
||||||
match self {
|
match self {
|
||||||
Ok(val) => Reply(ReplyItem::Message(val.into())), //val.from_request(req),
|
Ok(val) => Ok(Reply(ReplyItem::Message(val.into()))),
|
||||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Into<Error>> FromRequest for StdResult<Reply, E> {
|
impl<E: Into<Error>> FromRequest for Result<Reply, E> {
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = Reply;
|
||||||
match self {
|
type Error = E;
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
fn from_request(self, _: HttpRequest) -> Result<Reply, E> {
|
||||||
}
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Into<Error>> From<StdResult<Reply, E>> for Reply {
|
impl<E: Into<Error>> From<Result<Reply, E>> for Reply {
|
||||||
fn from(res: StdResult<Reply, E>) -> Self {
|
fn from(res: Result<Reply, E>) -> Self {
|
||||||
match res {
|
match res {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
||||||
|
@ -119,23 +131,18 @@ impl<E: Into<Error>> From<StdResult<Reply, E>> for Reply {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Into<Error>> FromRequest for StdResult<HttpResponse, E> {
|
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
|
||||||
match self {
|
|
||||||
Ok(val) => Reply(ReplyItem::Message(val)),
|
|
||||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> FromRequest for HttpContext<A, S>
|
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> FromRequest for HttpContext<A, S>
|
||||||
{
|
{
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = Reply;
|
||||||
Reply(ReplyItem::Actor(Box::new(self)))
|
type Error = Error;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
|
Ok(Reply(ReplyItem::Actor(Box::new(self))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> for Reply {
|
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> for Reply {
|
||||||
|
|
||||||
fn from(ctx: HttpContext<A, S>) -> Reply {
|
fn from(ctx: HttpContext<A, S>) -> Reply {
|
||||||
Reply(ReplyItem::Actor(Box::new(ctx)))
|
Reply(ReplyItem::Actor(Box::new(ctx)))
|
||||||
}
|
}
|
||||||
|
@ -143,8 +150,11 @@ impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> fo
|
||||||
|
|
||||||
impl FromRequest for Box<Future<Item=HttpResponse, Error=Error>>
|
impl FromRequest for Box<Future<Item=HttpResponse, Error=Error>>
|
||||||
{
|
{
|
||||||
fn from_request(self, _: HttpRequest) -> Reply {
|
type Item = Reply;
|
||||||
Reply(ReplyItem::Future(self))
|
type Error = Error;
|
||||||
|
|
||||||
|
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
|
Ok(Reply(ReplyItem::Future(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +191,10 @@ impl<S, H, R> RouteHandler<S> for WrapHandler<S, H, R>
|
||||||
{
|
{
|
||||||
fn handle(&self, req: HttpRequest<S>) -> Reply {
|
fn handle(&self, req: HttpRequest<S>) -> Reply {
|
||||||
let req2 = req.clone_without_state();
|
let req2 = req.clone_without_state();
|
||||||
self.h.handle(req).from_request(req2)
|
match self.h.handle(req).from_request(req2) {
|
||||||
|
Ok(reply) => reply.into(),
|
||||||
|
Err(err) => Reply::response(err.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue