mirror of https://github.com/rwf2/Rocket.git
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!
This commit is contained in:
parent
4d4985a0e7
commit
dcb150bde7
|
@ -4,6 +4,11 @@
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
use rocket::Rocket;
|
use rocket::Rocket;
|
||||||
|
|
||||||
|
#[route(GET, path = "/")]
|
||||||
|
fn simple() -> &'static str {
|
||||||
|
"Hello, simple example world! How is thou?"
|
||||||
|
}
|
||||||
|
|
||||||
#[route(GET, path = "/<name>")]
|
#[route(GET, path = "/<name>")]
|
||||||
fn hello(name: String) -> String {
|
fn hello(name: String) -> String {
|
||||||
format!("Hello, {}!", name)
|
format!("Hello, {}!", name)
|
||||||
|
@ -16,5 +21,5 @@ fn bye(x: usize, y: usize) -> String {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let rocket = Rocket::new("localhost", 8000);
|
let rocket = Rocket::new("localhost", 8000);
|
||||||
rocket.mount_and_launch("/", routes![hello, bye]);
|
rocket.mount_and_launch("/", routes![simple, hello, bye]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ mod error;
|
||||||
mod response;
|
mod response;
|
||||||
mod request;
|
mod request;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
pub use method::Method;
|
pub use method::Method;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use response::Response;
|
pub use response::{Body, Response};
|
||||||
pub use request::Request;
|
pub use request::Request;
|
||||||
|
|
||||||
use hyper::server::Handler as HypHandler;
|
use hyper::server::Handler as HypHandler;
|
||||||
|
@ -16,27 +18,41 @@ use hyper::server::Response as HypResponse;
|
||||||
use hyper::net::Fresh as HypFresh;
|
use hyper::net::Fresh as HypFresh;
|
||||||
use hyper::Server;
|
use hyper::Server;
|
||||||
|
|
||||||
pub type Handler = fn(Request) -> Response;
|
pub type Handler<'a> = fn(Request) -> Response<'a>;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Route<'a> {
|
#[derive(Clone)]
|
||||||
|
pub struct Route<'a, 'b> {
|
||||||
pub method: Method,
|
pub method: Method,
|
||||||
pub path: &'a str,
|
pub path: &'a str,
|
||||||
pub handler: Handler
|
pub handler: Handler<'b>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Rocket {
|
pub struct Rocket {
|
||||||
address: &'static str,
|
address: &'static str,
|
||||||
port: isize,
|
port: isize,
|
||||||
|
handler: Option<Route<'static, 'static>> // just for testing
|
||||||
// mounts: HashMap<&'static str, Route<'a>>
|
// mounts: HashMap<&'static str, Route<'a>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HypHandler for Rocket {
|
impl HypHandler for Rocket {
|
||||||
fn handle<'a, 'k>(&'a self, req: HypRequest<'a, 'k>,
|
fn handle<'a, 'k>(&'a self, req: HypRequest<'a, 'k>,
|
||||||
res: HypResponse<'a, HypFresh>) {
|
mut res: HypResponse<'a, HypFresh>) {
|
||||||
println!("Request: {:?}", req.uri);
|
println!("Request: {:?}", req.uri);
|
||||||
res.send(b"Hello World!").unwrap();
|
if self.handler.is_some() {
|
||||||
|
let response = (self.handler.as_ref().unwrap().handler)(Request::empty());
|
||||||
|
*(res.headers_mut()) = response.headers;
|
||||||
|
*(res.status_mut()) = response.status;
|
||||||
|
match response.body {
|
||||||
|
Body::Str(string) => {
|
||||||
|
let mut stream = res.start().unwrap();
|
||||||
|
stream.write_all(string.as_bytes()).unwrap();
|
||||||
|
stream.end();
|
||||||
|
}
|
||||||
|
_ => println!("UNIMPLEMENTED")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,20 +60,25 @@ impl Rocket {
|
||||||
pub fn new(address: &'static str, port: isize) -> Rocket {
|
pub fn new(address: &'static str, port: isize) -> Rocket {
|
||||||
Rocket {
|
Rocket {
|
||||||
address: address,
|
address: address,
|
||||||
port: port
|
port: port,
|
||||||
|
handler: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount(&mut self, base: &str, routes: &[&Route]) -> &mut Self {
|
pub fn mount(&mut self, base: &str, routes: &[&Route<'static, 'static>]) -> &mut Self {
|
||||||
println!("🛰 Mounting '{}':", base);
|
println!("🛰 Mounting '{}':", base);
|
||||||
for route in routes {
|
for route in routes {
|
||||||
|
if self.handler.is_none() {
|
||||||
|
println!("\t* INSTALLED: {} '{}'", route.method, route.path);
|
||||||
|
self.handler = Some((*route).clone());
|
||||||
|
}
|
||||||
println!("\t* {} '{}'", route.method, route.path);
|
println!("\t* {} '{}'", route.method, route.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount_and_launch(mut self, base: &str, routes: &[&Route]) {
|
pub fn mount_and_launch(mut self, base: &str, routes: &[&Route<'static, 'static>]) {
|
||||||
self.mount(base, routes);
|
self.mount(base, routes);
|
||||||
self.launch();
|
self.launch();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@ use error::Error;
|
||||||
pub struct Request;
|
pub struct Request;
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
|
pub fn empty() -> Request {
|
||||||
|
Request
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_param_str(&self, name: &str) -> Result<&str, Error> {
|
pub fn get_param_str(&self, name: &str) -> Result<&str, Error> {
|
||||||
Err(Error::NoKey)
|
Err(Error::NoKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,67 @@
|
||||||
pub struct Response;
|
pub use hyper::status::StatusCode;
|
||||||
|
pub use hyper::header::{self, Headers};
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Response {
|
pub enum Body<'a> {
|
||||||
fn from(_s: &'a str) -> Self {
|
Bytes(&'a [u8]),
|
||||||
Response
|
Str(&'a str),
|
||||||
|
String(String),
|
||||||
|
Stream(Box<Read>),
|
||||||
|
Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Response<'a> {
|
||||||
|
pub status: StatusCode,
|
||||||
|
pub headers: Headers,
|
||||||
|
pub body: Body<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Response<'a> {
|
||||||
|
pub fn empty() -> Response<'a> {
|
||||||
|
Response {
|
||||||
|
status: StatusCode::Ok,
|
||||||
|
headers: Headers::new(),
|
||||||
|
body: Body::Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_found() -> Response<'a> {
|
||||||
|
Response {
|
||||||
|
status: StatusCode::NotFound,
|
||||||
|
headers: Headers::new(),
|
||||||
|
body: Body::Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn server_error() -> Response<'a> {
|
||||||
|
Response {
|
||||||
|
status: StatusCode::InternalServerError,
|
||||||
|
headers: Headers::new(),
|
||||||
|
body: Body::Empty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Response {
|
impl<'a> From<&'a str> for Response<'a> {
|
||||||
fn from(_s: String) -> Self {
|
fn from(s: &'a str) -> Self {
|
||||||
Response
|
let mut headers = Headers::new();
|
||||||
|
headers.set(header::ContentLength(s.len() as u64));
|
||||||
|
Response {
|
||||||
|
status: StatusCode::Ok,
|
||||||
|
headers: headers,
|
||||||
|
body: Body::Str(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl<'a> From<String> for Response<'a> {
|
||||||
pub fn error(number: usize) -> Response {
|
fn from(s: String) -> Self {
|
||||||
println!("ERROR {}!", number);
|
let mut headers = Headers::new();
|
||||||
Response
|
headers.set(header::ContentLength(s.len() as u64));
|
||||||
|
Response {
|
||||||
|
status: StatusCode::Ok,
|
||||||
|
headers: headers,
|
||||||
|
body: Body::String(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,9 +189,9 @@ pub fn route_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
|
||||||
for param in &fn_params {
|
for param in &fn_params {
|
||||||
let param_ident = str_to_ident(param.as_str());
|
let param_ident = str_to_ident(param.as_str());
|
||||||
fn_param_exprs.push(quote_stmt!(ecx,
|
fn_param_exprs.push(quote_stmt!(ecx,
|
||||||
let $param_ident = match req.get_param($param) {
|
let $param_ident = match _req.get_param($param) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => return rocket::Response::error(200)
|
Err(_) => return rocket::Response::not_found()
|
||||||
};
|
};
|
||||||
).unwrap());
|
).unwrap());
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ pub fn route_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
|
||||||
let route_fn_name = prepend_ident(FN_PREFIX, &item.ident);
|
let route_fn_name = prepend_ident(FN_PREFIX, &item.ident);
|
||||||
let fn_name = item.ident;
|
let fn_name = item.ident;
|
||||||
let route_fn_item = quote_item!(ecx,
|
let route_fn_item = quote_item!(ecx,
|
||||||
fn $route_fn_name(req: rocket::Request) -> rocket::Response {
|
fn $route_fn_name<'a>(_req: rocket::Request) -> rocket::Response<'a> {
|
||||||
$fn_param_exprs
|
$fn_param_exprs
|
||||||
let result = $fn_name($fn_param_idents);
|
let result = $fn_name($fn_param_idents);
|
||||||
rocket::Response::from(result)
|
rocket::Response::from(result)
|
||||||
|
@ -223,7 +223,7 @@ pub fn route_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
|
||||||
let method = method_variant_to_expr(ecx, route_params.method);
|
let method = method_variant_to_expr(ecx, route_params.method);
|
||||||
push(Annotatable::Item(quote_item!(ecx,
|
push(Annotatable::Item(quote_item!(ecx,
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub static $struct_name: rocket::Route<'static> = rocket::Route {
|
pub static $struct_name: rocket::Route<'static, 'static> = rocket::Route {
|
||||||
method: $method,
|
method: $method,
|
||||||
path: $path,
|
path: $path,
|
||||||
handler: $route_fn_name
|
handler: $route_fn_name
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub fn routes_macro(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
|
||||||
last_seg.identifier = new_ident;
|
last_seg.identifier = new_ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build up the P<Expr> for each &path.
|
// Build up the P<Expr> for each path.
|
||||||
let path_exprs = paths.iter().map(|p| { quote_expr!(ecx, &$p) }).collect();
|
let path_exprs = paths.iter().map(|p| { quote_expr!(ecx, &$p) }).collect();
|
||||||
MacEager::expr(ecx.expr_vec_slice(sp, path_exprs))
|
MacEager::expr(ecx.expr_vec_slice(sp, path_exprs))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue