#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;
#[cfg(feature = "multipart")]
use multipart::server::{HttpRequest, Multipart};
use std::io::{self, Read};
use hyper::buffer::BufReader;
use hyper::http::h1::HttpReader;
use hyper::net::NetworkStream;
use context::Parameters;
use header::Headers;
pub struct BodyReader<'a, 'b: 'a> {
reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>,
#[cfg(feature = "multipart")]
multipart_boundary: Option<String>
}
impl<'a, 'b> BodyReader<'a, 'b> {
#[doc(hidden)]
#[cfg(feature = "multipart")]
pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, headers: &Headers) -> BodyReader<'a, 'b> {
use header::ContentType;
use mime::{Mime, TopLevel, SubLevel, Attr, Value};
let boundary = match headers.get() {
Some(&ContentType(Mime(TopLevel::Multipart, SubLevel::FormData, ref attrs))) => {
attrs.iter()
.find(|&&(ref attr, _)| attr == &Attr::Boundary)
.and_then(|&(_, ref val)| if let Value::Ext(ref boundary) = *val {
Some(boundary.clone())
} else {
None
})
},
_ => None
};
BodyReader {
reader: reader,
multipart_boundary: boundary
}
}
#[doc(hidden)]
#[cfg(not(feature = "multipart"))]
pub fn from_reader(reader: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>, _headers: &Headers) -> BodyReader<'a, 'b> {
BodyReader {
reader: reader
}
}
}
impl<'a, 'b> BodyReader<'a, 'b> {
#[cfg(feature = "multipart")]
pub fn as_multipart<'r>(&'r mut self) -> Option<Multipart<MultipartRequest<'r, 'a, 'b>>> {
let reader = &mut self.reader;
self.multipart_boundary.as_ref().and_then(move |boundary|
Multipart::from_request(MultipartRequest {
boundary: boundary,
reader: reader
}).ok()
)
}
#[inline]
pub fn read_query_body(&mut self) -> io::Result<Parameters> {
let mut buf = Vec::new();
try!(self.read_to_end(&mut buf));
Ok(::utils::parse_parameters(&buf))
}
#[cfg(feature = "rustc_json_body")]
pub fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
json::Json::from_reader(self)
}
#[cfg(feature = "rustc_json_body")]
pub fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
let mut buf = String::new();
try!(self.read_to_string(&mut buf).map_err(|e| {
let parse_err = json::ParserError::IoError(e);
json::DecoderError::ParseError(parse_err)
}));
json::decode(&buf)
}
}
impl<'a, 'b> Read for BodyReader<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reader.read(buf)
}
}
#[cfg(feature = "multipart")]
pub struct MultipartRequest<'r, 'a: 'r, 'b: 'a> {
boundary: &'r str,
reader: &'r mut HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}
#[cfg(feature = "multipart")]
impl<'r, 'a, 'b> HttpRequest for MultipartRequest<'r, 'a, 'b> {
fn multipart_boundary(&self) -> Option<&str> {
Some(self.boundary)
}
}
#[cfg(feature = "multipart")]
impl<'r, 'a, 'b> Read for MultipartRequest<'r, 'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reader.read(buf)
}
}