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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
#![cfg_attr(test, deny(warnings))] extern crate rustc_serialize; extern crate conduit; extern crate conduit_middleware as middleware; extern crate conduit_utils as utils; use std::any::Any; use std::error::Error; use std::io::prelude::*; use std::marker; use rustc_serialize::Decodable; use rustc_serialize::json::{self, Json}; use conduit::Request; use middleware::Middleware; pub struct BodyReader<T> { _marker: marker::PhantomData<fn() -> T>, } impl<T: Decodable + Any> BodyReader<T> { pub fn new() -> BodyReader<T> { BodyReader { _marker: marker::PhantomData } } } impl<T: Decodable + Any> Middleware for BodyReader<T> { fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> { let json: T = try!(decode::<T>(req.body())); req.mut_extensions().insert(json); Ok(()) } } #[allow(trivial_casts)] fn decode<T: Decodable>(reader: &mut Read) -> Result<T, Box<Error+Send>> { let j = try!(Json::from_reader(reader).map_err(|e| Box::new(e) as Box<Error+Send>)); let mut decoder = json::Decoder::new(j); Decodable::decode(&mut decoder).map_err(|e| Box::new(e) as Box<Error+Send>) } pub fn json_params<'a, T: Decodable + Any>(req: &'a Request) -> Option<&'a T> { req.extensions().find::<T>() } #[cfg(test)] mod tests { extern crate conduit_test; use {json_params, BodyReader}; use std::collections::HashMap; use std::io::{self, Cursor}; use rustc_serialize::json; use conduit::{Request, Response, Handler, Method}; use middleware::MiddlewareBuilder; #[derive(PartialEq, RustcDecodable, RustcEncodable, Debug)] struct Person { name: String, location: String } fn handler(req: &mut Request) -> io::Result<Response> { let person = json_params::<Person>(req); let out = person.map(|p| json::encode(p).unwrap()).expect("No JSON"); Ok(Response { status: (200, "OK"), headers: HashMap::new(), body: Box::new(Cursor::new(out.into_bytes())) }) } #[test] fn test_body_params() { let mut req = conduit_test::MockRequest::new(Method::Get, "/"); req.with_body(br#"{ "name": "Alex Crichton", "location": "San Francisco" }"#); let mut middleware = MiddlewareBuilder::new(handler); middleware.add(BodyReader::<Person>::new()); let mut res = middleware.call(&mut req).ok().expect("No response"); let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response"); assert_eq!(person, Person { name: "Alex Crichton".to_string(), location: "San Francisco".to_string() }); } }