use std::net::{ToSocketAddrs, SocketAddr};
use std::time::Duration;
pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::{Fresh, SslServer, HttpListener, HttpsListener, NetworkListener};
use request::HttpRequest;
use response::HttpResponse;
use error::HttpResult;
use {Request, Handler};
use status;
pub struct Iron<H> {
pub handler: H,
pub timeouts: Timeouts,
pub threads: usize,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Timeouts {
pub keep_alive: Option<Duration>,
pub read: Option<Duration>,
pub write: Option<Duration>
}
impl Default for Timeouts {
fn default() -> Self {
Timeouts {
keep_alive: Some(Duration::from_secs(5)),
read: Some(Duration::from_secs(30)),
write: Some(Duration::from_secs(1))
}
}
}
#[derive(Clone)]
enum _Protocol {
Http,
Https,
}
#[derive(Clone)]
pub struct Protocol(_Protocol);
impl Protocol {
pub fn http() -> Protocol {
Protocol(_Protocol::Http)
}
pub fn https() -> Protocol {
Protocol(_Protocol::Https)
}
pub fn name(&self) -> &str {
match self.0 {
_Protocol::Http => "http",
_Protocol::Https => "https",
}
}
}
impl<H: Handler> Iron<H> {
pub fn new(handler: H) -> Iron<H> {
Iron {
handler: handler,
timeouts: Timeouts::default(),
threads: 8 * ::num_cpus::get(),
}
}
pub fn http<A>(self, addr: A) -> HttpResult<Listening>
where A: ToSocketAddrs
{
HttpListener::new(addr).and_then(|l| self.listen(l, Protocol::http()))
}
pub fn https<A, S>(self, addr: A, ssl: S) -> HttpResult<Listening>
where A: ToSocketAddrs,
S: 'static + SslServer + Send + Clone
{
HttpsListener::new(addr, ssl).and_then(|l| self.listen(l, Protocol::http()))
}
pub fn listen<L>(self, mut listener: L, protocol: Protocol) -> HttpResult<Listening>
where L: 'static + NetworkListener + Send
{
let handler = RawHandler {
handler: self.handler,
addr: try!(listener.local_addr()),
protocol: protocol,
};
let mut server = Server::new(listener);
server.keep_alive(self.timeouts.keep_alive);
server.set_read_timeout(self.timeouts.read);
server.set_write_timeout(self.timeouts.write);
server.handle_threads(handler, self.threads)
}
}
struct RawHandler<H> {
handler: H,
addr: SocketAddr,
protocol: Protocol,
}
impl<H: Handler> ::hyper::server::Handler for RawHandler<H> {
fn handle(&self, http_req: HttpRequest, mut http_res: HttpResponse<Fresh>) {
*http_res.status_mut() = status::InternalServerError;
match Request::from_http(http_req, self.addr, &self.protocol) {
Ok(mut req) => {
self.handler.handle(&mut req).unwrap_or_else(|e| {
error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
e.response
}).write_back(http_res)
},
Err(e) => {
error!("Error creating request:\n {}", e);
bad_request(http_res)
}
}
}
}
fn bad_request(mut http_res: HttpResponse<Fresh>) {
*http_res.status_mut() = status::BadRequest;
if let Ok(res) = http_res.start()
{
let _ = res.end();
}
}