2016-08-26 08:55:11 +00:00
|
|
|
use std::io::{Read};
|
|
|
|
use std::cell::RefCell;
|
2016-08-27 01:37:28 +00:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
use term_painter::Color::*;
|
|
|
|
use term_painter::ToStyle;
|
2016-08-26 08:55:11 +00:00
|
|
|
|
2016-03-15 03:43:52 +00:00
|
|
|
use error::Error;
|
2016-03-17 08:57:04 +00:00
|
|
|
use param::FromParam;
|
2016-07-16 04:09:08 +00:00
|
|
|
use method::Method;
|
2016-03-15 03:43:52 +00:00
|
|
|
|
2016-08-26 08:55:11 +00:00
|
|
|
use content_type::ContentType;
|
|
|
|
use hyper::uri::RequestUri as HyperRequestUri;
|
|
|
|
use hyper::header;
|
|
|
|
use router::URIBuf;
|
|
|
|
use router::URI;
|
|
|
|
use router::Route;
|
|
|
|
|
|
|
|
// Hyper stuff.
|
|
|
|
use request::{HyperHeaders, HyperRequest};
|
|
|
|
|
2016-03-22 05:04:39 +00:00
|
|
|
pub struct Request<'a> {
|
2016-07-16 04:09:08 +00:00
|
|
|
pub method: Method,
|
2016-08-26 08:55:11 +00:00
|
|
|
pub uri: URIBuf, // FIXME: Should be URI (without Hyper).
|
|
|
|
pub data: Vec<u8>, // FIXME: Don't read this! (bad Hyper.)
|
2016-08-27 01:37:28 +00:00
|
|
|
params: RefCell<Option<Vec<&'a str>>>, // This also sucks.
|
2016-08-26 08:55:11 +00:00
|
|
|
headers: HyperHeaders, // This sucks.
|
2016-03-22 05:04:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Request<'a> {
|
2016-09-07 06:24:20 +00:00
|
|
|
pub fn get_param<T: FromParam<'a>>(&self, n: usize) -> Result<T, Error> {
|
2016-08-26 08:55:11 +00:00
|
|
|
let params = self.params.borrow();
|
|
|
|
if params.is_none() || n >= params.as_ref().unwrap().len() {
|
|
|
|
Err(Error::NoKey)
|
|
|
|
} else {
|
|
|
|
T::from_param(params.as_ref().unwrap()[n])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mock(method: Method, uri: &str) -> Request {
|
2016-03-22 05:04:39 +00:00
|
|
|
Request {
|
2016-08-26 08:55:11 +00:00
|
|
|
params: RefCell::new(None),
|
2016-07-16 04:09:08 +00:00
|
|
|
method: method,
|
2016-08-26 08:55:11 +00:00
|
|
|
uri: URIBuf::from(uri),
|
|
|
|
data: vec![],
|
|
|
|
headers: HyperHeaders::new()
|
2016-03-22 05:04:39 +00:00
|
|
|
}
|
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-08-26 08:55:11 +00:00
|
|
|
// FIXME: Get rid of Hyper.
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn headers(&self) -> &HyperHeaders {
|
|
|
|
&self.headers
|
2016-03-15 03:43:52 +00:00
|
|
|
}
|
|
|
|
|
2016-08-27 12:10:29 +00:00
|
|
|
// FIXME: This should be an Option. Not all requests have content types.
|
2016-08-26 08:55:11 +00:00
|
|
|
pub fn content_type(&self) -> ContentType {
|
|
|
|
let hyp_ct = self.headers().get::<header::ContentType>();
|
|
|
|
hyp_ct.map_or(ContentType::any(), |ct| ContentType::from(&ct.0))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn uri(&'a self) -> URI<'a> {
|
|
|
|
self.uri.as_uri()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_params(&'a self, route: &Route) {
|
|
|
|
*self.params.borrow_mut() = Some(route.get_params(self.uri.as_uri()))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub fn set_content_type(&mut self, ct: ContentType) {
|
|
|
|
let hyper_ct = header::ContentType(ct.into());
|
|
|
|
self.headers.set::<header::ContentType>(hyper_ct)
|
|
|
|
}
|
|
|
|
|
2016-08-27 01:37:28 +00:00
|
|
|
pub fn from_hyp<'h, 'k>(hyper_req: HyperRequest<'h, 'k>)
|
|
|
|
-> Result<Request<'a>, String> {
|
2016-08-26 08:55:11 +00:00
|
|
|
let (_, h_method, h_headers, h_uri, _, mut h_body) = hyper_req.deconstruct();
|
|
|
|
|
|
|
|
let uri = match h_uri {
|
|
|
|
HyperRequestUri::AbsolutePath(s) => URIBuf::from(s),
|
2016-08-27 01:37:28 +00:00
|
|
|
_ => return Err(format!("Bad URI: {}", h_uri))
|
|
|
|
};
|
|
|
|
|
|
|
|
let method = match Method::from_hyp(&h_method) {
|
|
|
|
Some(m) => m,
|
|
|
|
_ => return Err(format!("Bad method: {}", h_method))
|
2016-08-26 08:55:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME: GRRR.
|
|
|
|
let mut data = vec![];
|
|
|
|
h_body.read_to_end(&mut data).unwrap();
|
|
|
|
|
2016-08-27 01:37:28 +00:00
|
|
|
let request = Request {
|
2016-08-26 08:55:11 +00:00
|
|
|
params: RefCell::new(None),
|
2016-08-27 01:37:28 +00:00
|
|
|
method: method,
|
2016-08-26 08:55:11 +00:00
|
|
|
uri: uri,
|
|
|
|
data: data,
|
|
|
|
headers: h_headers,
|
2016-08-27 01:37:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(request)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> fmt::Display for Request<'r> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{} {}", Green.paint(&self.method), Blue.paint(&self.uri))
|
2016-03-15 03:43:52 +00:00
|
|
|
}
|
|
|
|
}
|