1#![crate_name = "bodyparser"]
2
3extern crate iron;
8extern crate plugin;
9extern crate persistent;
10extern crate serde;
11extern crate serde_json;
12
13use serde::Deserialize;
14use serde_json::{from_str, from_value};
15
16use iron::mime;
17use iron::prelude::*;
18use iron::headers;
19use iron::typemap::{Key};
20use std::io::Read;
21use std::any::Any;
22use std::marker;
23
24pub use self::errors::{BodyError, BodyErrorCause};
25pub use self::limit_reader::{LimitReader};
26
27mod errors;
28mod limit_reader;
29
30fn read_body_as_utf8(req: &mut Request, limit: usize) -> Result<String, errors::BodyError> {
31 let mut bytes = Vec::new();
32 match LimitReader::new(req.body.by_ref(), limit).read_to_end(&mut bytes) {
33 Ok(_) => {
34 match String::from_utf8(bytes) {
35 Ok(e) => Ok(e),
36 Err(err) => Err(errors::BodyError {
37 detail: "Invalid UTF-8 sequence".to_string(),
38 cause: errors::BodyErrorCause::Utf8Error(err.utf8_error())
39 })
40 }
41 },
42 Err(err) => Err(errors::BodyError {
43 detail: "Can't read request body".to_string(),
44 cause: errors::BodyErrorCause::IoError(err)
45 })
46 }
47}
48
49pub struct MaxBodyLength;
51impl Key for MaxBodyLength {
52 type Value = usize;
53}
54
55pub struct Raw;
58
59impl Key for Raw {
60 type Value = Option<String>;
61}
62
63const DEFAULT_BODY_LIMIT: usize = 1024 * 1024 * 100;
64
65impl<'a, 'b> plugin::Plugin<Request<'a, 'b>> for Raw {
66 type Error = BodyError;
67
68 fn eval(req: &mut Request) -> Result<Option<String>, BodyError> {
69 let need_read = req.headers.get::<headers::ContentType>().map(|header| {
70 match **header {
71 mime::Mime(mime::TopLevel::Multipart, mime::SubLevel::FormData, _) => false,
72 _ => true
73 }
74 }).unwrap_or(false);
75
76 if need_read {
77 let max_length = req
78 .get::<persistent::Read<MaxBodyLength>>()
79 .ok()
80 .map(|x| *x)
81 .unwrap_or(DEFAULT_BODY_LIMIT);
82
83 let body = try!(read_body_as_utf8(req, max_length));
84 Ok(Some(body))
85 } else {
86 Ok(None)
87 }
88 }
89}
90
91#[derive(Clone)]
94pub struct Json;
95impl Key for Json {
96 type Value = Option<serde_json::Value>;
97}
98
99impl<'a, 'b> plugin::Plugin<Request<'a, 'b>> for Json {
100 type Error = BodyError;
101
102 fn eval(req: &mut Request) -> Result<Option<serde_json::Value>, BodyError> {
103 req.get::<Raw>()
104 .and_then(|maybe_body| {
105 reverse_option(maybe_body.map(|body| from_str(&body)))
106 .map_err(|err| {
107 BodyError {
108 detail: "Can't parse body to JSON".to_string(),
109 cause: BodyErrorCause::JsonError(err)
110 }
111 })
112 })
113 }
114}
115
116pub struct Struct<T> where T: for<'a> Deserialize<'a> {
119 marker: marker::PhantomData<T>
120}
121impl<T> Key for Struct<T> where T: for<'a> Deserialize<'a> + Any {
122 type Value = Option<T>;
123}
124
125impl<'a, 'b, T> plugin::Plugin<Request<'a, 'b>> for Struct<T>
126where T: for<'c> Deserialize<'c> + Any {
127 type Error = BodyError;
128
129 fn eval(req: &mut Request) -> Result<Option<T>, BodyError> {
130 req.get::<Json>()
131 .and_then(|maybe_body| {
132 reverse_option(maybe_body.map(|body| from_value(body)))
133 .map_err(|err| BodyError {
134 detail: "Can't parse body to the struct".to_string(),
135 cause: BodyErrorCause::JsonError(err)
136 })
137 })
138 }
139}
140
141fn reverse_option<T,E>(value: Option<Result<T, E>>) -> Result<Option<T>, E> {
142 match value {
143 Some(Ok(val)) => Ok(Some(val)),
144 Some(Err(err)) => Err(err),
145 None => Ok(None),
146 }
147}