Skip to content

Instantly share code, notes, and snippets.

@pzol
Last active August 29, 2015 14:13
Show Gist options
  • Save pzol/749a202deaf06c4aaaaf to your computer and use it in GitHub Desktop.
Save pzol/749a202deaf06c4aaaaf to your computer and use it in GitHub Desktop.
use std::io::{self, IoResult, MemReader};
use hyper::status;
use hyper::net::Fresh;
pub use hyper::server::Response as HttpResponse;
use hyper::header::Headers;
pub struct Response {
pub body: Option<Box<Reader + Send>>
}
pub trait IntoReader {
type OutReader: Reader;
fn into_reader(self) -> Self::OutReader;
}
impl Response {
pub fn new() -> Response {
Response { body: None }
}
pub fn set_body<I>(&mut self, data: I)
where I: IntoReader, <I as IntoReader>::OutReader: Send {
self.body = Some(Box::new(data.into_reader()));
}
pub fn with_body<I>(data: I) -> Response
where I: IntoReader, <I as IntoReader>::OutReader: Send {
let mut res = Response::new();
res.body = Some(Box::new(data.into_reader()));
res
}
pub fn write_back(self, mut http_res: HttpResponse<Fresh>) {
// *http_res.headers_mut() = self.headers;
// Default to a 404 if no response code was set
// *http_res.status_mut() = self.status.clone().unwrap_or(status::NotFound);
let out = match self.body {
Some(body) => write_with_body(http_res, body),
None => {
// http_res.headers_mut().set(headers::ContentLength(0));
http_res.start().and_then(|res| res.end())
}
};
match out {
Err(e) => {
error!("Error writing response: {}", e);
},
_ => {}
}
}
}
impl IntoReader for String {
type OutReader = MemReader;
fn into_reader(self) -> MemReader {
MemReader::new(self.into_bytes())
}
}
// impl IntoReader for Path {
// type OutReader = File;
// fn into_reader(self) -> File {
// File::open(self).unwrap()
// }
// }
fn write_with_body(mut res: HttpResponse<Fresh>, mut body: Box<Reader + Send>) -> IoResult<()> {
// let content_type = res.headers().get::<headers::ContentType>()
// .map(|cx| cx.clone())
// .unwrap_or_else(|| headers::ContentType("text/plain".parse().unwrap()));
// res.headers_mut().set(content_type);
let mut res = try!(res.start());
// FIXME: Manually inlined io::util::copy
// because Box<Reader + Send> does not impl Reader.
//
// Tracking issue: rust-lang/rust#18542
let mut buf = &mut [0; 1024 * 64];
loop {
let len = match body.read(buf) {
Ok(len) => len,
Err(ref e) if e.kind == io::EndOfFile => break,
Err(e) => { return Err(e) },
};
try!(res.write(&buf[..len]))
}
res.end()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment