2016-03-28 09:34:09 +00:00
|
|
|
use std::io::{Read, Write};
|
|
|
|
use std::fs::File;
|
|
|
|
use std::fmt;
|
|
|
|
|
2016-10-04 00:09:13 +00:00
|
|
|
use response::Outcome;
|
|
|
|
use http::mime::{Mime, TopLevel, SubLevel};
|
|
|
|
use http::hyper::{header, FreshHyperResponse, StatusCode};
|
|
|
|
|
2016-04-02 08:51:22 +00:00
|
|
|
// TODO: Have this return something saying whether every was okay. Need
|
|
|
|
// something like to be able to forward requests on when things don't work out.
|
|
|
|
// In particular, we want to try the next ranked route when when parsing
|
|
|
|
// parameters doesn't work out.
|
2016-03-28 09:34:09 +00:00
|
|
|
pub trait Responder {
|
2016-04-11 10:57:23 +00:00
|
|
|
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a>;
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Responder for &'a str {
|
2016-08-02 02:07:36 +00:00
|
|
|
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
2016-08-27 01:37:28 +00:00
|
|
|
if res.headers().get::<header::ContentType>().is_none() {
|
|
|
|
let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![]);
|
|
|
|
res.headers_mut().set(header::ContentType(mime));
|
|
|
|
}
|
|
|
|
|
2016-03-28 09:34:09 +00:00
|
|
|
res.send(self.as_bytes()).unwrap();
|
2016-04-11 10:57:23 +00:00
|
|
|
Outcome::Complete
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Responder for String {
|
2016-08-02 02:07:36 +00:00
|
|
|
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-08-27 01:37:28 +00:00
|
|
|
if res.headers().get::<header::ContentType>().is_none() {
|
|
|
|
let mime = Mime(TopLevel::Text, SubLevel::Html, vec![]);
|
|
|
|
res.headers_mut().set(header::ContentType(mime));
|
|
|
|
}
|
2016-03-28 09:34:09 +00:00
|
|
|
res.send(self.as_bytes()).unwrap();
|
2016-04-11 10:57:23 +00:00
|
|
|
Outcome::Complete
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Should we set a content-type here? Safari needs text/html to render.
|
2016-08-02 02:07:36 +00:00
|
|
|
// Unfortunately, the file name is gone at this point. Should fix this. There's
|
|
|
|
// a way to retrieve a file based on its fd, strangely enough. See...
|
|
|
|
// https://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c
|
2016-03-28 09:34:09 +00:00
|
|
|
impl Responder for File {
|
2016-04-11 10:57:23 +00:00
|
|
|
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-03-28 09:34:09 +00:00
|
|
|
let size = self.metadata().unwrap().len();
|
|
|
|
|
|
|
|
res.headers_mut().set(header::ContentLength(size));
|
|
|
|
*(res.status_mut()) = StatusCode::Ok;
|
|
|
|
|
|
|
|
let mut v = Vec::new();
|
|
|
|
self.read_to_end(&mut v).unwrap();
|
|
|
|
|
|
|
|
let mut stream = res.start().unwrap();
|
|
|
|
stream.write_all(&v).unwrap();
|
2016-04-11 10:57:23 +00:00
|
|
|
Outcome::Complete
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Responder> Responder for Option<T> {
|
2016-04-11 10:57:23 +00:00
|
|
|
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-03-28 09:34:09 +00:00
|
|
|
if self.is_none() {
|
2016-08-24 08:30:09 +00:00
|
|
|
trace!("Option is none.");
|
2016-03-28 09:34:09 +00:00
|
|
|
// TODO: Should this be a 404 or 500?
|
2016-08-02 02:07:36 +00:00
|
|
|
return Outcome::FailForward(res);
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 10:57:23 +00:00
|
|
|
self.as_mut().unwrap().respond(res)
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Responder, E: fmt::Debug> Responder for Result<T, E> {
|
|
|
|
// prepend with `default` when using impl specialization
|
2016-09-30 22:20:11 +00:00
|
|
|
default fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-03-28 09:34:09 +00:00
|
|
|
if self.is_err() {
|
2016-08-24 08:30:09 +00:00
|
|
|
error_!("{:?}", self.as_ref().err().unwrap());
|
2016-03-28 09:34:09 +00:00
|
|
|
// TODO: Should this be a 404 or 500?
|
2016-08-02 02:07:36 +00:00
|
|
|
return Outcome::FailForward(res);
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 10:57:23 +00:00
|
|
|
self.as_mut().unwrap().respond(res)
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Responder, E: Responder + fmt::Debug> Responder for Result<T, E> {
|
2016-04-11 10:57:23 +00:00
|
|
|
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-04-23 02:48:03 +00:00
|
|
|
match *self {
|
|
|
|
Ok(ref mut responder) => responder.respond(res),
|
2016-09-30 22:20:11 +00:00
|
|
|
Err(ref mut responder) => responder.respond(res),
|
2016-03-28 09:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|