1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//!
//! JSON support (parsing/responder) based on serde_json
//!

extern crate finchers;
extern crate serde;
extern crate serde_json;

// TODO: make the dependency for hyper through finchers, rather than directly dependency.
extern crate hyper;

pub use self::serde_json::{Error, Value};

use hyper::{header, mime};
use self::serde::ser::Serialize;
use self::serde::de::DeserializeOwned;

use finchers::endpoint::body::{body, Body};
use finchers::request::{FromBody, Request};
use finchers::response::{Responder, Response};


/// Represents a JSON value
#[derive(Debug)]
pub struct Json<T = Value>(pub T);

impl<T: DeserializeOwned> FromBody for Json<T> {
    type Error = Error;

    fn check_request(req: &Request) -> bool {
        req.media_type()
            .map_or(false, |m| *m == mime::APPLICATION_JSON)
    }

    fn from_body(body: Vec<u8>) -> Result<Self, Self::Error> {
        serde_json::from_slice(&body).map(Json)
    }
}

impl<T: Serialize> Responder for Json<T> {
    type Error = Error;

    fn respond(self) -> Result<Response, Self::Error> {
        let body = serde_json::to_vec(&self.0)?;
        let len = body.len();
        Ok(Response::new()
            .with_header(header::ContentType::json())
            .with_header(header::ContentLength(len as u64))
            .with_body(body))
    }
}

/// Create an endpoint with parsing JSON body
pub fn json_body<T: DeserializeOwned>() -> Body<Json<T>> {
    body::<Json<T>>()
}