diff --git a/guide/src/qs_12.md b/guide/src/qs_12.md index dd7f6acf..102f4f94 100644 --- a/guide/src/qs_12.md +++ b/guide/src/qs_12.md @@ -23,7 +23,7 @@ fn main() { ## Directory -To serve all files from specific directory `StaticFiles` type could be used. +To serve files from specific directory and sub-directories `StaticFiles` type could be used. `StaticFiles` could be registered with `Application::route` method. ```rust @@ -36,6 +36,6 @@ fn main() { } ``` -First parameter is a base directory. Second parameter is `show_index`, if it set to *true* +First parameter is a base directory. Second parameter is *show_index*, if it is set to *true* directory listing would be returned for directories, if it is set to *false* then *404 Not Found* would be returned instead of directory listing. diff --git a/guide/src/qs_7.md b/guide/src/qs_7.md index b5b91d59..bfbcb657 100644 --- a/guide/src/qs_7.md +++ b/guide/src/qs_7.md @@ -13,3 +13,29 @@ Following encodings are supported: If request headers contains `Content-Encoding` header, request payload get decompressed according to header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`. +## JSON Response + +The `Json` type allows you to respond with well-formed JSON data: simply return a value of +type Json where T is the type of a structure to serialize into *JSON*. The +type `T` must implement the `Serialize` trait from *serde*. + +```rust +extern crate actix_web; +#[macro_use] extern crate serde_derive; +use actix_web::*; + +#[derive(Serialize)] +struct MyObj { + name: String, +} + +fn index(req: HttpRequest) -> Result> { + Ok(Json(MyObj{name: req.match_info().query("name")?})) +} + +fn main() { + Application::default("/") + .resource(r"/a/{name}", |r| r.get(index)) + .finish(); +} +``` diff --git a/src/lib.rs b/src/lib.rs index 61c6a0a4..6b90a391 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,8 @@ extern crate percent_encoding; extern crate actix; extern crate h2 as http2; -// extern crate redis_async; +#[cfg(test)] +#[macro_use] extern crate serde_derive; #[cfg(feature="tls")] extern crate native_tls; @@ -81,7 +82,7 @@ pub use application::Application; pub use httprequest::{HttpRequest, UrlEncoded}; pub use httpresponse::HttpResponse; pub use payload::{Payload, PayloadItem}; -pub use route::{Reply, FromRequest}; +pub use route::{Reply, Json, FromRequest}; pub use resource::Resource; pub use recognizer::Params; pub use server::HttpServer; diff --git a/src/route.rs b/src/route.rs index cb35da70..25223924 100644 --- a/src/route.rs +++ b/src/route.rs @@ -2,6 +2,8 @@ use std::marker::PhantomData; use actix::Actor; use futures::Future; +use serde_json; +use serde::Serialize; use error::Error; use context::{HttpContext, IoContext}; @@ -223,3 +225,37 @@ impl RouteHandler for AsyncHandler Reply::async((self.f)(req)) } } + + +pub struct Json (pub T); + +impl FromRequest for Json { + type Item = HttpResponse; + type Error = Error; + + fn from_request(self, _: HttpRequest) -> Result { + let body = serde_json::to_string(&self.0)?; + + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use http::header; + + #[derive(Serialize)] + struct MyObj { + name: &'static str, + } + + #[test] + fn test_json() { + let json = Json(MyObj{name: "test"}); + let resp = json.from_request(HttpRequest::default()).unwrap(); + assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/json"); + } +}