2016-03-19 02:05:29 +00:00
|
|
|
#![feature(str_char)]
|
2016-03-28 09:34:09 +00:00
|
|
|
#![feature(specialization)]
|
2016-03-19 02:05:29 +00:00
|
|
|
|
2016-03-21 09:22:22 +00:00
|
|
|
extern crate term_painter;
|
2016-03-12 18:45:19 +00:00
|
|
|
extern crate hyper;
|
|
|
|
|
2016-03-17 08:57:04 +00:00
|
|
|
pub mod method;
|
|
|
|
pub mod error;
|
|
|
|
pub mod response;
|
|
|
|
pub mod request;
|
|
|
|
pub mod param;
|
2016-03-17 10:29:55 +00:00
|
|
|
pub mod router;
|
2016-03-12 18:45:19 +00:00
|
|
|
|
|
|
|
pub use method::Method;
|
|
|
|
pub use error::Error;
|
2016-03-15 03:43:52 +00:00
|
|
|
pub use request::Request;
|
2016-03-17 08:57:04 +00:00
|
|
|
pub use param::FromParam;
|
2016-03-17 10:29:55 +00:00
|
|
|
pub use router::Router;
|
2016-03-28 09:34:09 +00:00
|
|
|
pub use response::{Response, HypResponse, Responder, HypFresh};
|
2016-03-12 18:45:19 +00:00
|
|
|
|
2016-03-21 09:22:22 +00:00
|
|
|
use std::fmt;
|
2016-03-30 08:02:21 +00:00
|
|
|
use std::io::Read;
|
2016-03-21 09:22:22 +00:00
|
|
|
use term_painter::ToStyle;
|
|
|
|
use term_painter::Color::*;
|
|
|
|
use hyper::uri::RequestUri;
|
2016-03-12 18:45:19 +00:00
|
|
|
use hyper::server::Handler as HypHandler;
|
|
|
|
use hyper::server::Request as HypRequest;
|
|
|
|
use hyper::Server;
|
|
|
|
|
Something works! A simple hacked-up handler, that is.
At the moment, I simply install the first route I see into the Rocket struct
directly. This is quite terrible. What's worse is that I assume that the Route's
path and handler are static! The handler, actually, does have to be static, but
its response may have whatever (valid) lifetime, though I'm not sure anything
but `static makes sense. I'll think about it.
In any case, the weird `static` restrictions need to be removed, and I need to
think about which lifetimes are safe here. IE: Must all routes be static? Can I
use a closure as a route? (that'd be neat). If so, how do we make that work?
In any case, it's nice to see SOMETHING work. Yay!
2016-03-15 07:41:22 +00:00
|
|
|
pub type Handler<'a> = fn(Request) -> Response<'a>;
|
2016-03-12 18:45:19 +00:00
|
|
|
|
2016-03-28 09:34:09 +00:00
|
|
|
// TODO: Figure out if using 'static for Handler is a good idea.
|
|
|
|
// TODO: Merge this `Route` and route::Route, somewhow.
|
2016-03-22 05:04:39 +00:00
|
|
|
pub struct Route {
|
2016-03-12 18:45:19 +00:00
|
|
|
pub method: Method,
|
2016-03-17 08:57:04 +00:00
|
|
|
pub path: &'static str,
|
2016-03-22 05:04:39 +00:00
|
|
|
pub handler: Handler<'static>
|
2016-03-12 18:45:19 +00:00
|
|
|
}
|
|
|
|
|
2016-03-22 23:27:12 +00:00
|
|
|
impl Route {
|
2016-03-28 09:34:09 +00:00
|
|
|
pub fn new(method: Method, path: &'static str, handler: Handler<'static>)
|
|
|
|
-> Route {
|
2016-03-22 23:27:12 +00:00
|
|
|
Route {
|
|
|
|
method: method,
|
|
|
|
path: path,
|
|
|
|
handler: handler
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-22 05:04:39 +00:00
|
|
|
impl<'a> fmt::Display for Route {
|
2016-03-21 09:22:22 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{} {:?}", Green.paint(&self.method), Blue.paint(&self.path))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-12 18:45:19 +00:00
|
|
|
pub struct Rocket {
|
|
|
|
address: &'static str,
|
|
|
|
port: isize,
|
2016-03-17 10:29:55 +00:00
|
|
|
router: Router
|
2016-03-12 18:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HypHandler for Rocket {
|
2016-03-30 08:02:21 +00:00
|
|
|
fn handle<'a, 'k>(&'a self, mut req: HypRequest<'a, 'k>,
|
2016-03-18 03:37:34 +00:00
|
|
|
res: HypResponse<'a, HypFresh>) {
|
2016-03-28 09:34:09 +00:00
|
|
|
println!("{} {:?} {:?}", White.paint("Incoming:"),
|
|
|
|
Green.paint(&req.method), Blue.paint(&req.uri));
|
2016-03-30 08:02:21 +00:00
|
|
|
let mut buf = vec![];
|
|
|
|
req.read_to_end(&mut buf); // FIXME: Simple DOS attack here.
|
|
|
|
|
2016-03-21 09:22:22 +00:00
|
|
|
if let RequestUri::AbsolutePath(uri_string) = req.uri {
|
|
|
|
if let Some(method) = Method::from_hyp(req.method) {
|
2016-03-30 08:02:21 +00:00
|
|
|
|
2016-03-22 05:04:39 +00:00
|
|
|
let uri_str = uri_string.as_str();
|
|
|
|
let route = self.router.route(method, uri_str);
|
|
|
|
let mut response = route.map_or(Response::not_found(), |route| {
|
|
|
|
let params = route.get_params(uri_str);
|
|
|
|
let request = Request::new(params, uri_str);
|
|
|
|
(route.handler)(request)
|
|
|
|
});
|
|
|
|
|
2016-03-28 09:34:09 +00:00
|
|
|
println!("{}", Green.paint("\t=> Dispatched request."));
|
|
|
|
return response.respond(res);
|
2016-03-21 09:22:22 +00:00
|
|
|
}
|
2016-03-28 09:34:09 +00:00
|
|
|
|
|
|
|
println!("{}", Yellow.paint("\t=> Debug: Method::from_hyp failed!"));
|
Something works! A simple hacked-up handler, that is.
At the moment, I simply install the first route I see into the Rocket struct
directly. This is quite terrible. What's worse is that I assume that the Route's
path and handler are static! The handler, actually, does have to be static, but
its response may have whatever (valid) lifetime, though I'm not sure anything
but `static makes sense. I'll think about it.
In any case, the weird `static` restrictions need to be removed, and I need to
think about which lifetimes are safe here. IE: Must all routes be static? Can I
use a closure as a route? (that'd be neat). If so, how do we make that work?
In any case, it's nice to see SOMETHING work. Yay!
2016-03-15 07:41:22 +00:00
|
|
|
}
|
2016-03-21 09:22:22 +00:00
|
|
|
|
2016-03-28 09:34:09 +00:00
|
|
|
println!("{}", Red.paint("\t=> Dispatch failed. Returning 404."));
|
|
|
|
Response::not_found().respond(res);
|
2016-03-12 18:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rocket {
|
|
|
|
pub fn new(address: &'static str, port: isize) -> Rocket {
|
|
|
|
Rocket {
|
|
|
|
address: address,
|
Something works! A simple hacked-up handler, that is.
At the moment, I simply install the first route I see into the Rocket struct
directly. This is quite terrible. What's worse is that I assume that the Route's
path and handler are static! The handler, actually, does have to be static, but
its response may have whatever (valid) lifetime, though I'm not sure anything
but `static makes sense. I'll think about it.
In any case, the weird `static` restrictions need to be removed, and I need to
think about which lifetimes are safe here. IE: Must all routes be static? Can I
use a closure as a route? (that'd be neat). If so, how do we make that work?
In any case, it's nice to see SOMETHING work. Yay!
2016-03-15 07:41:22 +00:00
|
|
|
port: port,
|
2016-03-17 10:29:55 +00:00
|
|
|
router: Router::new()
|
2016-03-12 18:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-22 05:04:39 +00:00
|
|
|
pub fn mount(&mut self, base: &'static str, routes: &[&Route]) -> &mut Self {
|
2016-03-21 09:22:22 +00:00
|
|
|
println!("🛰 {} '{}':", Magenta.paint("Mounting"), Blue.paint(base));
|
2016-03-12 18:45:19 +00:00
|
|
|
for route in routes {
|
2016-03-21 09:22:22 +00:00
|
|
|
println!("\t* {}", route);
|
2016-03-22 05:04:39 +00:00
|
|
|
self.router.add_route(route.method, base, route.path, route.handler);
|
2016-03-12 18:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-03-22 05:04:39 +00:00
|
|
|
pub fn mount_and_launch(mut self, base: &'static str, routes: &[&Route]) {
|
2016-03-12 18:45:19 +00:00
|
|
|
self.mount(base, routes);
|
|
|
|
self.launch();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn launch(self) {
|
2016-03-17 10:29:55 +00:00
|
|
|
if self.router.has_collisions() {
|
2016-03-21 09:22:22 +00:00
|
|
|
println!("{}", Yellow.paint("Warning: route collisions detected!"));
|
2016-03-17 10:29:55 +00:00
|
|
|
}
|
|
|
|
|
2016-03-12 18:45:19 +00:00
|
|
|
let full_addr = format!("{}:{}", self.address, self.port);
|
2016-03-21 09:22:22 +00:00
|
|
|
println!("🚀 {} {}...", White.paint("Rocket has launched from"),
|
|
|
|
White.bold().paint(&full_addr));
|
2016-03-12 18:45:19 +00:00
|
|
|
let _ = Server::http(full_addr.as_str()).unwrap().handle(self);
|
|
|
|
}
|
|
|
|
}
|