From 8f411c9d8c437ec7108893daad65eaf3dcf241e9 Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Fri, 3 Jul 2015 14:23:23 +0100 Subject: [PATCH 1/4] feat(server): add some shared data across all requests This can be used to add some compile time dependencies for Middleware and Plugins. You can add bounds to `D` in the above to place compile-time restrictions on the server data (can be used for configuration). BREAKING CHANGE There is a default for the type-param to help mitigate breakage, but some code will probably still be significantly broken by this. To fix code broken by this, you will need to introduce a type parameter for various nickel types including: Request, Response, Middleware, MiddlewareResult and NickelError. ``` // e.g. This: fn foo<'mw>(&mut Request, Response<'mw>) -> MiddlewareResult<'mw> // Should become: fn foo<'mw, D>(&mut Request, Response<'mw, D>) -> MiddlewareResult<'mw, D> // Or you can use a concrete type: fn foo<'mw>(&mut Request, Response<'mw, MyType>) -> MiddlewareResult<'mw, MyType> ``` --- examples/macro_example.rs | 6 +-- src/default_error_handler.rs | 4 +- src/favicon_handler.rs | 13 +++---- src/json_body_parser.rs | 7 ++-- src/macros/middleware.rs | 10 ++--- src/middleware.rs | 38 +++++++++---------- src/mount.rs | 22 +++++------ src/nickel.rs | 37 ++++++++++++------- src/nickel_error.rs | 26 ++++++------- src/query_string.rs | 6 +-- src/request.rs | 24 ++++++++---- src/responder.rs | 34 ++++++++--------- src/response.rs | 71 +++++++++++++++++++++--------------- src/router/http_router.rs | 16 ++++---- src/router/router.rs | 42 ++++++++++----------- src/server.rs | 30 +++++++++------ src/static_files_handler.rs | 13 ++++--- 17 files changed, 219 insertions(+), 180 deletions(-) diff --git a/examples/macro_example.rs b/examples/macro_example.rs index d0a8431658..1449afc2a7 100644 --- a/examples/macro_example.rs +++ b/examples/macro_example.rs @@ -19,13 +19,13 @@ struct Person { } //this is an example middleware function that just logs each request -fn logger<'a>(request: &mut Request, response: Response<'a>) -> MiddlewareResult<'a> { +fn logger<'a, D>(request: &mut Request, response: Response<'a, D>) -> MiddlewareResult<'a, D> { println!("logging request: {:?}", request.origin.uri); Ok(Continue(response)) } //this is how to overwrite the default error handler to handle 404 cases with a custom view -fn custom_404<'a>(err: &mut NickelError, _req: &mut Request) -> Action { +fn custom_404<'a, D>(err: &mut NickelError, _req: &mut Request) -> Action { if let Some(ref mut res) = err.stream { if res.status() == NotFound { let _ = res.write_all(b"

Call the police!

"); @@ -122,7 +122,7 @@ fn main() { )); // issue #20178 - let custom_handler: fn(&mut NickelError, &mut Request) -> Action = custom_404; + let custom_handler: fn(&mut NickelError<()>, &mut Request<()>) -> Action = custom_404; server.handle_error(custom_handler); diff --git a/src/default_error_handler.rs b/src/default_error_handler.rs index 33cec2786e..75fb4b88f3 100644 --- a/src/default_error_handler.rs +++ b/src/default_error_handler.rs @@ -7,8 +7,8 @@ use std::io::Write; #[derive(Clone, Copy)] pub struct DefaultErrorHandler; -impl ErrorHandler for DefaultErrorHandler { - fn handle_error(&self, err: &mut NickelError, _req: &mut Request) -> Action { +impl ErrorHandler for DefaultErrorHandler { + fn handle_error(&self, err: &mut NickelError, _req: &mut Request) -> Action { if let Some(ref mut res) = err.stream { let msg : &[u8] = match res.status() { NotFound => b"Not Found", diff --git a/src/favicon_handler.rs b/src/favicon_handler.rs index 5d3d191eb8..eaa13314f1 100644 --- a/src/favicon_handler.rs +++ b/src/favicon_handler.rs @@ -6,7 +6,6 @@ use hyper::uri::RequestUri::AbsolutePath; use hyper::method::Method::{Get, Head, Options}; use hyper::status::StatusCode; use hyper::header; -use hyper::net; use request::Request; use response::Response; @@ -18,9 +17,9 @@ pub struct FaviconHandler { icon_path: PathBuf, // Is it useful to log where in-memory favicon came from every request? } -impl Middleware for FaviconHandler { - fn invoke<'a, 'server>(&'a self, req: &mut Request<'a, 'server>, res: Response<'a, net::Fresh>) - -> MiddlewareResult<'a> { +impl Middleware for FaviconHandler { + fn invoke<'a, 'server>(&'a self, req: &mut Request<'a, 'server, D>, res: Response<'a, D>) + -> MiddlewareResult<'a, D> { if FaviconHandler::is_favicon_request(req) { self.handle_request(req, res) } else { @@ -53,14 +52,14 @@ impl FaviconHandler { } #[inline] - pub fn is_favicon_request(req: &Request) -> bool { + pub fn is_favicon_request(req: &Request) -> bool { match req.origin.uri { AbsolutePath(ref path) => &**path == "/favicon.ico", _ => false } } - pub fn handle_request<'a>(&self, req: &Request, mut res: Response<'a>) -> MiddlewareResult<'a> { + pub fn handle_request<'a, D>(&self, req: &Request, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> { match req.origin.method { Get | Head => { self.send_favicon(req, res) @@ -78,7 +77,7 @@ impl FaviconHandler { } } - pub fn send_favicon<'a, 'server>(&self, req: &Request, mut res: Response<'a>) -> MiddlewareResult<'a> { + pub fn send_favicon<'a, D>(&self, req: &Request, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> { debug!("{:?} {:?}", req.origin.method, self.icon_path.display()); res.set(MediaType::Ico); res.send(&*self.icon) diff --git a/src/json_body_parser.rs b/src/json_body_parser.rs index 3f8b0c179e..29009fe9d7 100644 --- a/src/json_body_parser.rs +++ b/src/json_body_parser.rs @@ -8,10 +8,11 @@ use std::io::{Read, ErrorKind}; // Plugin boilerplate struct JsonBodyParser; impl Key for JsonBodyParser { type Value = String; } -impl<'mw, 'conn> Plugin> for JsonBodyParser { + +impl<'mw, 'conn, D> Plugin> for JsonBodyParser { type Error = io::Error; - fn eval(req: &mut Request) -> Result { + fn eval(req: &mut Request) -> Result { let mut s = String::new(); try!(req.origin.read_to_string(&mut s)); Ok(s) @@ -22,7 +23,7 @@ pub trait JsonBody { fn json_as(&mut self) -> Result; } -impl<'mw, 'conn> JsonBody for Request<'mw, 'conn> { +impl<'mw, 'conn, D> JsonBody for Request<'mw, 'conn, D> { fn json_as(&mut self) -> Result { self.get_ref::().and_then(|parsed| json::decode::(&*parsed).map_err(|err| diff --git a/src/macros/middleware.rs b/src/macros/middleware.rs index c13b16cc40..b8977b9170 100644 --- a/src/macros/middleware.rs +++ b/src/macros/middleware.rs @@ -38,18 +38,18 @@ macro_rules! _middleware_inner { use $crate::{MiddlewareResult,Responder, Response, Request}; #[inline(always)] - fn restrict<'mw, R: Responder>(r: R, res: Response<'mw>) - -> MiddlewareResult<'mw> { + fn restrict<'mw, D, R: Responder>(r: R, res: Response<'mw, D>) + -> MiddlewareResult<'mw, D> { res.send(r) } // Inference fails due to thinking it's a (&Request, Response) with // different mutability requirements #[inline(always)] - fn restrict_closure(f: F) -> F + fn restrict_closure(f: F) -> F where F: for<'r, 'mw, 'conn> - Fn(&'r mut Request<'mw, 'conn>, Response<'mw>) - -> MiddlewareResult<'mw> + Send + Sync { f } + Fn(&'r mut Request<'mw, 'conn, D>, Response<'mw, D>) + -> MiddlewareResult<'mw, D> + Send + Sync { f } restrict_closure(move |as_pat!($req), $res_binding| { restrict(as_block!({$($b)+}), $res) diff --git a/src/middleware.rs b/src/middleware.rs index 6f86bacdda..d373f11753 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -5,9 +5,9 @@ use hyper::net; pub use self::Action::{Continue, Halt}; -pub type MiddlewareResult<'mw> = Result, - Response<'mw, net::Streaming>>, - NickelError<'mw>>; +pub type MiddlewareResult<'mw, D> = Result, + Response<'mw, D, net::Streaming>>, + NickelError<'mw, D>>; pub enum Action { Continue(T), @@ -16,43 +16,43 @@ pub enum Action { // the usage of + Send is weird here because what we really want is + Static // but that's not possible as of today. We have to use + Send for now. -pub trait Middleware: Send + 'static + Sync { - fn invoke<'mw, 'conn>(&'mw self, _req: &mut Request<'mw, 'conn>, res: Response<'mw, net::Fresh>) -> MiddlewareResult<'mw> { +pub trait Middleware: Send + 'static + Sync { + fn invoke<'mw, 'conn>(&'mw self, _req: &mut Request<'mw, 'conn, D>, res: Response<'mw, D, net::Fresh>) -> MiddlewareResult<'mw, D> { Ok(Continue(res)) } } -impl Middleware for T where T: for<'r, 'mw, 'conn> Fn(&'r mut Request<'mw, 'conn>, Response<'mw>) -> MiddlewareResult<'mw> + Send + Sync + 'static { - fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { +impl Middleware for T where T: for<'r, 'mw, 'conn> Fn(&'r mut Request<'mw, 'conn, D>, Response<'mw, D>) -> MiddlewareResult<'mw, D> + Send + Sync + 'static { + fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn, D>, res: Response<'mw, D>) -> MiddlewareResult<'mw, D> { (*self)(req, res) } } -pub trait ErrorHandler: Send + 'static + Sync { - fn handle_error(&self, &mut NickelError, &mut Request) -> Action; +pub trait ErrorHandler: Send + 'static + Sync { + fn handle_error(&self, &mut NickelError, &mut Request) -> Action; } -impl ErrorHandler for fn(&mut NickelError, &mut Request) -> Action { - fn handle_error(&self, err: &mut NickelError, req: &mut Request) -> Action { +impl ErrorHandler for fn(&mut NickelError, &mut Request) -> Action { + fn handle_error(&self, err: &mut NickelError, req: &mut Request) -> Action { (*self)(err, req) } } -pub struct MiddlewareStack { - handlers: Vec>, - error_handlers: Vec> +pub struct MiddlewareStack { + handlers: Vec + Send + Sync>>, + error_handlers: Vec + Send + Sync>> } -impl MiddlewareStack { - pub fn add_middleware (&mut self, handler: T) { +impl MiddlewareStack { + pub fn add_middleware> (&mut self, handler: T) { self.handlers.push(Box::new(handler)); } - pub fn add_error_handler (&mut self, handler: T) { + pub fn add_error_handler> (&mut self, handler: T) { self.error_handlers.push(Box::new(handler)); } - pub fn invoke<'mw, 'conn>(&'mw self, mut req: Request<'mw, 'conn>, mut res: Response<'mw>) { + pub fn invoke<'mw, 'conn>(&'mw self, mut req: Request<'mw, 'conn, D>, mut res: Response<'mw, D>) { for handler in self.handlers.iter() { match handler.invoke(&mut req, res) { Ok(Halt(res)) => { @@ -92,7 +92,7 @@ impl MiddlewareStack { } } - pub fn new () -> MiddlewareStack { + pub fn new () -> MiddlewareStack { MiddlewareStack{ handlers: Vec::new(), error_handlers: Vec::new() diff --git a/src/mount.rs b/src/mount.rs index c376dd098a..e898e49d2c 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -7,12 +7,12 @@ use hyper::uri::RequestUri::AbsolutePath; use std::mem; -pub trait Mountable { - fn mount, M: Middleware>(&mut self, mount_point: S, middleware: M); +pub trait Mountable { + fn mount, M: Middleware>(&mut self, mount_point: S, middleware: M); } -impl Mountable for Nickel { - /// +impl Mountable for Nickel +where D: Send + Sync + 'static { /// A trait that makes mounting more convenient. Works the same as /// manually adding a `Mount` middleware. /// @@ -27,17 +27,17 @@ impl Mountable for Nickel { /// /// # Panics /// Panics if mount_point does not have a leading and trailing slash. - fn mount, M: Middleware>(&mut self, mount_point: S, middleware: M) { + fn mount, M: Middleware>(&mut self, mount_point: S, middleware: M) { self.utilize(Mount::new(mount_point, middleware)); } } -pub struct Mount { +pub struct Mount { mount_point: String, middleware: M } -impl Mount { +impl Mount { /// /// Creates a new middleware that mounts a middleware at a mount point. /// An incoming request that matches the mount point will be forwareded to @@ -63,7 +63,7 @@ impl Mount { pub fn new>(mount_point: S, middleware: M) -> Mount { let mount_point: String = mount_point.into(); match (mount_point.chars().last(), mount_point.chars().nth(0)) { - (Some('/'), Some('/')) => + (Some('/'), Some('/')) => Mount { mount_point: mount_point, middleware: middleware @@ -73,9 +73,9 @@ impl Mount { } } -impl Middleware for Mount { - fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn>, res: Response<'mw>) - -> MiddlewareResult<'mw> { +impl> Middleware for Mount { + fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn, D>, res: Response<'mw, D>) + -> MiddlewareResult<'mw, D> { let subpath = match req.origin.uri { AbsolutePath(ref path) if path.starts_with(&*self.mount_point) => { AbsolutePath(format!("/{}", &path[self.mount_point.len()..])) diff --git a/src/nickel.rs b/src/nickel.rs index 82d045fb89..ae479a3301 100644 --- a/src/nickel.rs +++ b/src/nickel.rs @@ -10,12 +10,13 @@ use default_error_handler::DefaultErrorHandler; /// Nickel is the application object. It's the surface that /// holds all public APIs. -pub struct Nickel{ - middleware_stack: MiddlewareStack, +pub struct Nickel { + middleware_stack: MiddlewareStack, + data: D } -impl HttpRouter for Nickel { - fn add_route, H: Middleware>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self { +impl HttpRouter for Nickel { + fn add_route, H: Middleware>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self { let mut router = Router::new(); router.add_route(method, matcher, handler); self.utilize(router); @@ -23,9 +24,16 @@ impl HttpRouter for Nickel { } } -impl Nickel { +impl Nickel<()> { /// Creates an instance of Nickel with default error handling. - pub fn new() -> Nickel { + pub fn new() -> Nickel<()> { + Nickel::with_data(()) + } +} + +impl Nickel { + /// Creates an instance of Nickel with default error handling and custom data. + pub fn with_data(data: D) -> Nickel { let mut middleware_stack = MiddlewareStack::new(); // Hook up the default error handler by default. Users are @@ -33,7 +41,10 @@ impl Nickel { // they don't like the default behaviour. middleware_stack.add_error_handler(DefaultErrorHandler); - Nickel { middleware_stack: middleware_stack } + Nickel { + middleware_stack: middleware_stack, + data: data + } } /// Registers a middleware handler which will be invoked among other middleware @@ -57,7 +68,7 @@ impl Nickel { /// }); /// # } /// ``` - pub fn utilize(&mut self, handler: T){ + pub fn utilize>(&mut self, handler: T){ self.middleware_stack.add_middleware(handler); } @@ -77,7 +88,7 @@ impl Nickel { /// use nickel::{NickelError, Action}; /// use nickel::status::StatusCode::NotFound; /// - /// fn error_handler(err: &mut NickelError, _req: &mut Request) -> Action { + /// fn error_handler(err: &mut NickelError, _req: &mut Request) -> Action { /// if let Some(ref mut res) = err.stream { /// if res.status() == NotFound { /// let _ = res.write_all(b"

Call the police!

"); @@ -90,12 +101,12 @@ impl Nickel { /// /// let mut server = Nickel::new(); /// - /// let ehandler: fn(&mut NickelError, &mut Request) -> Action = error_handler; + /// let ehandler: fn(&mut NickelError<()>, &mut Request<()>) -> Action = error_handler; /// /// server.handle_error(ehandler) /// # } /// ``` - pub fn handle_error(&mut self, handler: T){ + pub fn handle_error>(&mut self, handler: T){ self.middleware_stack.add_error_handler(handler); } @@ -118,7 +129,7 @@ impl Nickel { /// server.utilize(router); /// } /// ``` - pub fn router() -> Router { + pub fn router() -> Router { Router::new() } @@ -140,7 +151,7 @@ impl Nickel { (StatusCode::NotFound, "File Not Found") }); - let server = Server::new(self.middleware_stack); + let server = Server::new(self.middleware_stack, self.data); let listener = server.serve(addr).unwrap(); println!("Listening on http://{}", listener.socket); diff --git a/src/nickel_error.rs b/src/nickel_error.rs index 2362c3e1f0..2a92e7a032 100644 --- a/src/nickel_error.rs +++ b/src/nickel_error.rs @@ -7,12 +7,12 @@ use hyper::net::{Fresh, Streaming}; /// NickelError is the basic error type for HTTP errors as well as user defined errors. /// One can pattern match against the `kind` property to handle the different cases. -pub struct NickelError<'a> { - pub stream: Option>, +pub struct NickelError<'a, D: 'a = ()> { + pub stream: Option>, pub message: Cow<'static, str> } -impl<'a> NickelError<'a> { +impl<'a, D> NickelError<'a, D> { /// Creates a new `NickelError` instance. /// /// You should probably use `Response#error` in favor of this. @@ -26,14 +26,14 @@ impl<'a> NickelError<'a> { /// use nickel::status::StatusCode; /// /// # #[allow(dead_code)] - /// fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> { + /// fn handler<'a, D>(_: &mut Request, res: Response<'a, D>) -> MiddlewareResult<'a, D> { /// Err(NickelError::new(res, "Error Parsing JSON", StatusCode::BadRequest)) /// } /// # } /// ``` - pub fn new(mut stream: Response<'a, Fresh>, + pub fn new(mut stream: Response<'a, D, Fresh>, message: T, - status_code: StatusCode) -> NickelError<'a> + status_code: StatusCode) -> NickelError<'a, D> where T: Into> { stream.set(status_code); @@ -56,7 +56,7 @@ impl<'a> NickelError<'a> { /// /// This is considered `unsafe` as deadlock can occur if the `Response` /// does not have the underlying stream flushed when processing is finished. - pub unsafe fn without_response(message: T) -> NickelError<'a> + pub unsafe fn without_response(message: T) -> NickelError<'a, D> where T: Into> { NickelError { stream: None, @@ -69,22 +69,22 @@ impl<'a> NickelError<'a> { } } -impl<'a, T> From<(Response<'a>, (StatusCode, T))> for NickelError<'a> +impl<'a, T, D> From<(Response<'a, D>, (StatusCode, T))> for NickelError<'a, D> where T: Into> { - fn from((res, (errorcode, err)): (Response<'a>, (StatusCode, T))) -> NickelError<'a> { + fn from((res, (errorcode, err)): (Response<'a, D>, (StatusCode, T))) -> NickelError<'a, D> { let err = err.into(); NickelError::new(res, err.description().to_string(), errorcode) } } -impl<'a> From<(Response<'a>, String)> for NickelError<'a> { - fn from((res, msg): (Response<'a>, String)) -> NickelError<'a> { +impl<'a, D> From<(Response<'a, D>, String)> for NickelError<'a, D> { + fn from((res, msg): (Response<'a, D>, String)) -> NickelError<'a, D> { NickelError::new(res, msg, StatusCode::InternalServerError) } } -impl<'a> From<(Response<'a>, StatusCode)> for NickelError<'a> { - fn from((res, code): (Response<'a>, StatusCode)) -> NickelError<'a> { +impl<'a, D> From<(Response<'a, D>, StatusCode)> for NickelError<'a, D> { + fn from((res, code): (Response<'a, D>, StatusCode)) -> NickelError<'a, D> { NickelError::new(res, "", code) } } diff --git a/src/query_string.rs b/src/query_string.rs index 19eab05761..bef54ffc57 100644 --- a/src/query_string.rs +++ b/src/query_string.rs @@ -33,10 +33,10 @@ impl Query { struct QueryStringParser; impl Key for QueryStringParser { type Value = Query; } -impl<'mw, 'conn> Plugin> for QueryStringParser { +impl<'mw, 'conn, D> Plugin> for QueryStringParser { type Error = (); - fn eval(req: &mut Request) -> Result { + fn eval(req: &mut Request) -> Result { Ok(parse(&req.origin.uri)) } } @@ -46,7 +46,7 @@ pub trait QueryString { fn query(&mut self) -> &Query; } -impl<'mw, 'conn> QueryString for Request<'mw, 'conn> { +impl<'mw, 'conn, D> QueryString for Request<'mw, 'conn, D> { fn query(&mut self) -> &Query { self.get_ref::() .ok() diff --git a/src/request.rs b/src/request.rs index 2de6dda19b..bcd1fa4ab0 100644 --- a/src/request.rs +++ b/src/request.rs @@ -11,21 +11,25 @@ use hyper::uri::RequestUri::AbsolutePath; /// /// The lifetime `'server` represents the lifetime of data internal to /// the server. It is fixed and longer than `'mw`. -pub struct Request<'mw, 'server: 'mw> { +pub struct Request<'mw, 'server: 'mw, D: 'mw = ()> { ///the original `hyper::server::Request` pub origin: HyperRequest<'mw, 'server>, ///a `HashMap` holding all params with names and values - pub route_result: Option>, + pub route_result: Option>, - map: TypeMap + map: TypeMap, + + data: &'mw D, } -impl<'mw, 'server> Request<'mw, 'server> { - pub fn from_internal(req: HyperRequest<'mw, 'server>) -> Request<'mw, 'server> { +impl<'mw, 'server, D> Request<'mw, 'server, D> { + pub fn from_internal(req: HyperRequest<'mw, 'server>, + data: &'mw D) -> Request<'mw, 'server, D> { Request { origin: req, route_result: None, - map: TypeMap::new() + map: TypeMap::new(), + data: data } } @@ -39,9 +43,13 @@ impl<'mw, 'server> Request<'mw, 'server> { _ => None } } + + pub fn server_data(&self) -> &D { + &self.data + } } -impl<'mw, 'server> Extensible for Request<'mw, 'server> { +impl<'mw, 'server, D> Extensible for Request<'mw, 'server, D> { fn extensions(&self) -> &TypeMap { &self.map } @@ -51,4 +59,4 @@ impl<'mw, 'server> Extensible for Request<'mw, 'server> { } } -impl<'mw, 'server> Pluggable for Request<'mw, 'server> {} +impl<'mw, 'server, D> Pluggable for Request<'mw, 'server, D> {} diff --git a/src/responder.rs b/src/responder.rs index a4a9b13bd4..91098aaeae 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -21,28 +21,28 @@ use std::io::Write; /// also modifying the `Response` as required. /// /// Please see the examples for some uses. -pub trait Responder { - fn respond<'a>(self, Response<'a>) -> MiddlewareResult<'a>; +pub trait Responder { + fn respond<'a>(self, Response<'a, D>) -> MiddlewareResult<'a, D>; } -impl Responder for () { - fn respond<'a>(self, res: Response<'a>) -> MiddlewareResult<'a> { +impl Responder for () { + fn respond<'a>(self, res: Response<'a, D>) -> MiddlewareResult<'a, D> { Ok(Continue(res)) } } -impl Responder for json::Json { - fn respond<'a>(self, mut res: Response<'a>) -> MiddlewareResult<'a> { +impl Responder for json::Json { + fn respond<'a>(self, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> { maybe_set_type(&mut res, MediaType::Json); res.send(json::encode(&self) .map_err(|e| format!("Failed to parse JSON: {}", e))) } } -impl Responder for Result - where T: Responder, - for<'e> NickelError<'e>: From<(Response<'e>, E)> { - fn respond<'a>(self, res: Response<'a>) -> MiddlewareResult<'a> { +impl Responder for Result + where T: Responder, + for<'e> NickelError<'e, D>: From<(Response<'e, D>, E)> { + fn respond<'a>(self, res: Response<'a, D>) -> MiddlewareResult<'a, D> { let data = try_with!(res, self); res.send(data) } @@ -50,16 +50,16 @@ impl Responder for Result macro_rules! dual_impl { ($view:ty, $alloc:ty, |$s:ident, $res:ident| $b:block) => ( - impl<'a> Responder for $view { + impl<'a, D> Responder for $view { #[allow(unused_mut)] #[inline] - fn respond<'c>($s, mut $res: Response<'c>) -> MiddlewareResult<'c> $b + fn respond<'c>($s, mut $res: Response<'c, D>) -> MiddlewareResult<'c, D> $b } - impl<'a> Responder for $alloc { + impl<'a, D> Responder for $alloc { #[allow(unused_mut)] #[inline] - fn respond<'c>($s, mut $res: Response<'c>) -> MiddlewareResult<'c> $b + fn respond<'c>($s, mut $res: Response<'c, D>) -> MiddlewareResult<'c, D> $b } ) } @@ -99,9 +99,9 @@ dual_impl!((StatusCode, &'static str), } }); -impl<'a> Responder for StatusCode { +impl<'a, D> Responder for StatusCode { #[inline] - fn respond<'c>(self, res: Response<'c>) -> MiddlewareResult<'c> { + fn respond<'c>(self, res: Response<'c, D>) -> MiddlewareResult<'c, D> { res.send((self, "")) } } @@ -147,6 +147,6 @@ dual_impl!((u16, &'static str), // Ok(Halt) // }) -fn maybe_set_type(res: &mut Response, mime: MediaType) { +fn maybe_set_type(res: &mut Response, mime: MediaType) { res.set_header_fallback(|| header::ContentType(mime.into())); } diff --git a/src/response.rs b/src/response.rs index b791d954ad..589736b80f 100644 --- a/src/response.rs +++ b/src/response.rs @@ -23,19 +23,22 @@ use modifier::Modifier; pub type TemplateCache = RwLock>; ///A container for the response -pub struct Response<'a, T: 'static + Any = Fresh> { +pub struct Response<'a, D: 'a = (), T: 'static + Any = Fresh> { ///the original `hyper::server::Response` origin: HyperResponse<'a, T>, - templates: &'a TemplateCache + templates: &'a TemplateCache, + data: &'a D, } -impl<'a> Response<'a, Fresh> { +impl<'a, D> Response<'a, D, Fresh> { pub fn from_internal<'c, 'd>(response: HyperResponse<'c, Fresh>, - templates: &'c TemplateCache) - -> Response<'c, Fresh> { + templates: &'c TemplateCache, + data: &'c D) + -> Response<'c, D, Fresh> { Response { origin: response, - templates: templates + templates: templates, + data: data } } @@ -81,7 +84,7 @@ impl<'a> Response<'a, Fresh> { /// // ... /// } /// ``` - pub fn set>>(&mut self, attribute: T) -> &mut Response<'a> { + pub fn set>>(&mut self, attribute: T) -> &mut Response<'a, D> { attribute.modify(self); self } @@ -93,12 +96,12 @@ impl<'a> Response<'a, Fresh> { /// use nickel::{Request, Response, MiddlewareResult}; /// /// # #[allow(dead_code)] - /// fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> { + /// fn handler<'a, D>(_: &mut Request, res: Response<'a, D>) -> MiddlewareResult<'a, D> { /// res.send("hello world") /// } /// ``` #[inline] - pub fn send(self, data: T) -> MiddlewareResult<'a> { + pub fn send>(self, data: T) -> MiddlewareResult<'a, D> { data.respond(self) } @@ -110,12 +113,12 @@ impl<'a> Response<'a, Fresh> { /// use std::path::Path; /// /// # #[allow(dead_code)] - /// fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> { + /// fn handler<'a, D>(_: &mut Request, res: Response<'a, D>) -> MiddlewareResult<'a, D> { /// let favicon = Path::new("/assets/favicon.ico"); /// res.send_file(favicon) /// } /// ``` - pub fn send_file>(mut self, path: P) -> MiddlewareResult<'a> { + pub fn send_file>(mut self, path: P) -> MiddlewareResult<'a, D> { let path = path.as_ref(); // Chunk the response self.origin.headers_mut().remove::(); @@ -147,7 +150,7 @@ impl<'a> Response<'a, Fresh> { /// Return an error with the appropriate status code for error handlers to /// provide output for. - pub fn error(self, status: StatusCode, message: T) -> MiddlewareResult<'a> + pub fn error(self, status: StatusCode, message: T) -> MiddlewareResult<'a, D> where T: Into> { Err(NickelError::new(self, message, status)) } @@ -195,16 +198,16 @@ impl<'a> Response<'a, Fresh> { /// use nickel::{Request, Response, MiddlewareResult}; /// /// # #[allow(dead_code)] - /// fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> { + /// fn handler<'a, D>(_: &mut Request, res: Response<'a, D>) -> MiddlewareResult<'a, D> { /// let mut data = HashMap::new(); /// data.insert("name", "user"); /// res.render("examples/assets/template.tpl", &data) /// } /// ``` - pub fn render(self, path: P, data: &T) -> MiddlewareResult<'a> + pub fn render(self, path: P, data: &T) -> MiddlewareResult<'a, D> where T: Encodable, P: AsRef + Into { - fn render<'a, T>(res: Response<'a>, template: &Template, data: &T) - -> MiddlewareResult<'a> where T: Encodable { + fn render<'a, D, T>(res: Response<'a, D>, template: &Template, data: &T) + -> MiddlewareResult<'a, D> where T: Encodable { let mut stream = try!(res.start()); match template.render(&mut stream, data) { Ok(()) => Ok(Halt(stream)), @@ -239,21 +242,31 @@ impl<'a> Response<'a, Fresh> { render(self, template, data) } - pub fn start(mut self) -> Result, NickelError<'a>> { + pub fn start(mut self) -> Result, NickelError<'a, D>> { self.set_fallback_headers(); - let Response { origin, templates } = self; + let Response { origin, templates, data } = self; match origin.start() { - Ok(origin) => Ok(Response { origin: origin, templates: templates }), + Ok(origin) => { + Ok(Response { + origin: origin, + templates: templates, + data: data + }) + }, Err(e) => unsafe { Err(NickelError::without_response(format!("Failed to start response: {}", e))) } } } + + pub fn server_data(&self) -> &D { + &self.data + } } -impl<'a, 'b> Write for Response<'a, Streaming> { +impl<'a, 'b, D> Write for Response<'a, D, Streaming> { #[inline(always)] fn write(&mut self, buf: &[u8]) -> io::Result { self.origin.write(buf) @@ -265,12 +278,12 @@ impl<'a, 'b> Write for Response<'a, Streaming> { } } -impl<'a, 'b> Response<'a, Streaming> { +impl<'a, 'b, D> Response<'a, D, Streaming> { /// In the case of an unrecoverable error while a stream is already in /// progress, there is no standard way to signal to the client that an /// error has occurred. `bail` will drop the connection and log an error /// message. - pub fn bail(self, message: T) -> MiddlewareResult<'a> + pub fn bail(self, message: T) -> MiddlewareResult<'a, D> where T: Into> { let _ = self.end(); unsafe { Err(NickelError::without_response(message)) } @@ -282,7 +295,7 @@ impl<'a, 'b> Response<'a, Streaming> { } } -impl <'a, T: 'static + Any> Response<'a, T> { +impl <'a, D, T: 'static + Any> Response<'a, D, T> { /// The status of this response. pub fn status(&self) -> StatusCode { self.origin.status() @@ -315,14 +328,14 @@ mod modifier_impls { use modifier::Modifier; use {Response, MediaType}; - impl<'a> Modifier> for StatusCode { - fn modify(self, res: &mut Response<'a>) { + impl<'a, D> Modifier> for StatusCode { + fn modify(self, res: &mut Response<'a, D>) { *res.status_mut() = self } } - impl<'a> Modifier> for MediaType { - fn modify(self, res: &mut Response<'a>) { + impl<'a, D> Modifier> for MediaType { + fn modify(self, res: &mut Response<'a, D>) { ContentType(self.into()).modify(res) } } @@ -330,8 +343,8 @@ mod modifier_impls { macro_rules! header_modifiers { ($($t:ty),+) => ( $( - impl<'a> Modifier> for $t { - fn modify(self, res: &mut Response<'a>) { + impl<'a, D> Modifier> for $t { + fn modify(self, res: &mut Response<'a, D>) { res.headers_mut().set(self) } } diff --git a/src/router/http_router.rs b/src/router/http_router.rs index bf62eab6be..5df7502d95 100644 --- a/src/router/http_router.rs +++ b/src/router/http_router.rs @@ -2,7 +2,7 @@ use hyper::method::Method; use middleware::Middleware; use router::Matcher; -pub trait HttpRouter { +pub trait HttpRouter { /// Registers a handler to be used for a specified method. /// A handler can be anything implementing the `RequestHandler` trait. /// @@ -36,7 +36,7 @@ pub trait HttpRouter { /// server.add_route(Get, regex, middleware! { "Regex Get request! "}); /// } /// ``` - fn add_route, H: Middleware>(&mut self, Method, M, H) -> &mut Self; + fn add_route, H: Middleware>(&mut self, Method, M, H) -> &mut Self; /// Registers a handler to be used for a specific GET request. /// Handlers are assigned to paths and paths are allowed to contain @@ -121,42 +121,42 @@ pub trait HttpRouter { /// server.utilize(router); /// } /// ``` - fn get, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn get, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Get, matcher, handler) } /// Registers a handler to be used for a specific POST request. /// /// Take a look at `get(...)` for a more detailed description. - fn post, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn post, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Post, matcher, handler) } /// Registers a handler to be used for a specific PUT request. /// /// Take a look at `get(...)` for a more detailed description. - fn put, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn put, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Put, matcher, handler) } /// Registers a handler to be used for a specific DELETE request. /// /// Take a look at `get(...)` for a more detailed description. - fn delete, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn delete, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Delete, matcher, handler) } /// Registers a handler to be used for a specific OPTIONS request. /// /// Take a look at `get(...)` for a more detailed description. - fn options, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn options, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Options, matcher, handler) } /// Registers a handler to be used for a specific PATCH request. /// /// Take a look at `get(...)` for a more detailed description. - fn patch, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { + fn patch, H: Middleware>(&mut self, matcher: M, handler: H) -> &mut Self { self.add_route(Method::Patch, matcher, handler) } } diff --git a/src/router/router.rs b/src/router/router.rs index 261a5184e2..a86eb43f19 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -10,9 +10,9 @@ use router::{Matcher, FORMAT_PARAM}; /// A Route is the basic data structure that stores both the path /// and the handler that gets executed for the route. /// The path can contain variable pattern such as `user/:userid/invoices` -pub struct Route { +pub struct Route { pub method: Method, - pub handler: Box, + pub handler: Box + Send + Sync + 'static>, matcher: Matcher } @@ -20,12 +20,12 @@ pub struct Route { /// It contains the matched `route` and also a `params` property holding /// a HashMap with the keys being the variable names and the value being the /// evaluated string -pub struct RouteResult<'mw> { - pub route: &'mw Route, +pub struct RouteResult<'mw, D: 'mw = ()> { + pub route: &'mw Route, params: Vec<(String, String)> } -impl<'mw> RouteResult<'mw> { +impl<'mw, D> RouteResult<'mw, D> { pub fn param(&self, key: &str) -> Option<&str> { for &(ref k, ref v) in &self.params { if k == &key { @@ -45,18 +45,18 @@ impl<'mw> RouteResult<'mw> { /// The Router's job is it to hold routes and to resolve them later against /// concrete URLs. The router is also a regular middleware and needs to be /// added to the middleware stack with `server.utilize(router)`. -pub struct Router { - routes: Vec, +pub struct Router { + routes: Vec>, } -impl Router { - pub fn new () -> Router { +impl Router { + pub fn new() -> Router { Router { routes: Vec::new() } } - pub fn match_route<'mw>(&'mw self, method: &Method, path: &str) -> Option> { + pub fn match_route<'mw>(&'mw self, method: &Method, path: &str) -> Option> { self.routes .iter() .find(|item| item.method == *method && item.matcher.is_match(path)) @@ -69,7 +69,7 @@ impl Router { } } -fn extract_params(route: &Route, path: &str) -> Vec<(String, String)> { +fn extract_params(route: &Route, path: &str) -> Vec<(String, String)> { match route.matcher.captures(path) { Some(captures) => { captures.iter_named() @@ -82,8 +82,8 @@ fn extract_params(route: &Route, path: &str) -> Vec<(String, String)> { } } -impl HttpRouter for Router { - fn add_route, H: Middleware>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self { +impl HttpRouter for Router { + fn add_route, H: Middleware>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self { let route = Route { matcher: matcher.into(), method: method, @@ -95,9 +95,9 @@ impl HttpRouter for Router { } } -impl Middleware for Router { - fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn>, mut res: Response<'mw>) - -> MiddlewareResult<'mw> { +impl Middleware for Router { + fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn, D>, mut res: Response<'mw, D>) + -> MiddlewareResult<'mw, D> { debug!("Router::invoke for '{:?}'", req.origin.uri); // Strip off the querystring when matching a route @@ -191,7 +191,7 @@ fn creates_valid_regex_for_routes () { #[test] fn can_match_var_routes () { - let route_store = &mut Router::new(); + let route_store = &mut Router::<()>::new(); route_store.add_route(Method::Get, "/foo/:userid", middleware! { "hello from foo" }); route_store.add_route(Method::Get, "/bar", middleware! { "hello from foo" }); @@ -256,7 +256,7 @@ fn can_match_var_routes () { #[test] fn params_lifetime() { - let route_store = &mut Router::new(); + let route_store = &mut Router::<()>::new(); let handler = middleware! { "hello from foo" }; route_store.add_route(Method::Get, "/file/:format/:file", handler); @@ -276,7 +276,7 @@ fn params_lifetime() { fn regex_path() { use regex::Regex; - let route_store = &mut Router::new(); + let route_store = &mut Router::<()>::new(); let regex = Regex::new("/(foo|bar)").unwrap(); route_store.add_route(Method::Get, regex, middleware! { "hello from foo" }); @@ -298,7 +298,7 @@ fn regex_path() { fn regex_path_named() { use regex::Regex; - let route_store = &mut Router::new(); + let route_store = &mut Router::<()>::new(); let regex = Regex::new("/(?Pfoo|bar)/b").unwrap(); route_store.add_route(Method::Get, regex, middleware! { "hello from foo" }); @@ -323,7 +323,7 @@ fn regex_path_named() { fn ignores_querystring() { use regex::Regex; - let route_store = &mut Router::new(); + let route_store = &mut Router::<()>::new(); let regex = Regex::new("/(?Pfoo|bar)/b").unwrap(); route_store.add_route(Method::Get, regex, middleware! { "hello from foo" }); diff --git a/src/server.rs b/src/server.rs index b00990954a..f0c16575db 100644 --- a/src/server.rs +++ b/src/server.rs @@ -9,32 +9,38 @@ use middleware::MiddlewareStack; use request; use response; -pub struct Server { - middleware_stack: MiddlewareStack, - templates: response::TemplateCache +pub struct Server { + middleware_stack: MiddlewareStack, + templates: response::TemplateCache, + shared_data: D, } // FIXME: Any better coherence solutions? -struct ArcServer(Arc); +struct ArcServer(Arc>); -impl Handler for ArcServer { +impl Handler for ArcServer { fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a>) { - let req: Request<'a, 'k> = req; - let nickel_req = request::Request::from_internal(req); - let nickel_res = response::Response::from_internal(res, &self.0.templates); + let nickel_req = request::Request::from_internal(req, + &self.0.shared_data); + + let nickel_res = response::Response::from_internal(res, + &self.0.templates, + &self.0.shared_data); + self.0.middleware_stack.invoke(nickel_req, nickel_res); } } -impl Server { - pub fn new(middleware_stack: MiddlewareStack) -> Server { +impl Server { + pub fn new(middleware_stack: MiddlewareStack, data: D) -> Server { Server { middleware_stack: middleware_stack, - templates: RwLock::new(HashMap::new()) + templates: RwLock::new(HashMap::new()), + shared_data: data } } - pub fn serve(self, addr: T) -> HttpResult { + pub fn serve(self, addr: A) -> HttpResult { let arc = ArcServer(Arc::new(self)); let server = try!(HyperServer::http(addr)); server.handle(arc) diff --git a/src/static_files_handler.rs b/src/static_files_handler.rs index 51ad14e300..b726e1398a 100644 --- a/src/static_files_handler.rs +++ b/src/static_files_handler.rs @@ -15,8 +15,9 @@ pub struct StaticFilesHandler { root_path: PathBuf } -impl Middleware for StaticFilesHandler { - fn invoke<'a>(&self, req: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> { +impl Middleware for StaticFilesHandler { + fn invoke<'a>(&self, req: &mut Request, res: Response<'a, D>) + -> MiddlewareResult<'a, D> { match req.origin.method { Get | Head => self.with_file(self.extract_path(req), res), _ => Ok(Continue(res)) @@ -43,7 +44,7 @@ impl StaticFilesHandler { } } - fn extract_path<'a>(&self, req: &'a mut Request) -> Option<&'a str> { + fn extract_path<'a, D>(&self, req: &'a mut Request) -> Option<&'a str> { req.path_without_query().map(|path| { debug!("{:?} {:?}{:?}", req.origin.method, self.root_path.display(), path); @@ -54,10 +55,10 @@ impl StaticFilesHandler { }) } - fn with_file<'a, 'b, P>(&self, + fn with_file<'a, 'b, D, P>(&self, relative_path: Option

, - res: Response<'a>) - -> MiddlewareResult<'a> where P: AsRef { + res: Response<'a, D>) + -> MiddlewareResult<'a, D> where P: AsRef { if let Some(path) = relative_path { let path = self.root_path.join(path); match fs::metadata(&path) { From ffb5f21293a51dc29a3f7109560931ca810afe7e Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Sat, 4 Jul 2015 02:02:16 +0100 Subject: [PATCH 2/4] feat(response): allow Plugins for Response Also adds `on_send` which can be used to execute code when the Response headers are being sent. --- src/response.rs | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/response.rs b/src/response.rs index 589736b80f..16e9ac966e 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,3 +1,4 @@ +use std::mem; use std::borrow::Cow; use std::sync::RwLock; use std::collections::HashMap; @@ -19,6 +20,8 @@ use std::fs::File; use std::any::Any; use {NickelError, Halt, MiddlewareResult, Responder}; use modifier::Modifier; +use plugin::{Extensible, Pluggable}; +use typemap::TypeMap; pub type TemplateCache = RwLock>; @@ -28,6 +31,9 @@ pub struct Response<'a, D: 'a = (), T: 'static + Any = Fresh> { origin: HyperResponse<'a, T>, templates: &'a TemplateCache, data: &'a D, + map: TypeMap, + // This should be FnBox, but that's currently unstable + on_send: Vec)>> } impl<'a, D> Response<'a, D, Fresh> { @@ -38,7 +44,9 @@ impl<'a, D> Response<'a, D, Fresh> { Response { origin: response, templates: templates, - data: data + data: data, + map: TypeMap::new(), + on_send: vec![] } } @@ -243,15 +251,25 @@ impl<'a, D> Response<'a, D, Fresh> { } pub fn start(mut self) -> Result, NickelError<'a, D>> { + let on_send = mem::replace(&mut self.on_send, vec![]); + for mut f in on_send.into_iter().rev() { + // TODO: Ensure `f` doesn't call on_send again + f(&mut self) + } + + // Set fallback headers last after everything runs, if we did this before as an + // on_send then it would possibly set redundant things. self.set_fallback_headers(); - let Response { origin, templates, data } = self; + let Response { origin, templates, data, map, on_send } = self; match origin.start() { Ok(origin) => { Ok(Response { origin: origin, templates: templates, - data: data + data: data, + map: map, + on_send: on_send }) }, Err(e) => @@ -264,6 +282,11 @@ impl<'a, D> Response<'a, D, Fresh> { pub fn server_data(&self) -> &D { &self.data } + + pub fn on_send(&mut self, f: F) + where F: FnMut(&mut Response<'a, D, Fresh>) + 'static { + self.on_send.push(Box::new(f)) + } } impl<'a, 'b, D> Write for Response<'a, D, Streaming> { @@ -305,8 +328,24 @@ impl <'a, D, T: 'static + Any> Response<'a, D, T> { pub fn headers(&self) -> &Headers { self.origin.headers() } + + pub fn data(&self) -> &D { + &self.data + } } +impl<'a, D, T: 'static + Any> Extensible for Response<'a, D, T> { + fn extensions(&self) -> &TypeMap { + &self.map + } + + fn extensions_mut(&mut self) -> &mut TypeMap { + &mut self.map + } +} + +impl<'a, D, T: 'static + Any> Pluggable for Response<'a, D, T> {} + fn mime_from_filename>(path: P) -> Option { path.as_ref() .extension() From 86da30ef6ce8483527e79b48c58623b3721b327b Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Mon, 6 Jul 2015 01:13:33 +0100 Subject: [PATCH 3/4] chore(tests): update compile-fail tests --- tests/compile-fail/inference_fully_hinted.rs | 8 ++++---- tests/compile-fail/inference_no_hints.rs | 8 ++++---- tests/compile-fail/inference_request_hinted.rs | 8 ++++---- tests/compile-fail/inference_response_hinted.rs | 12 ++++++------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/compile-fail/inference_fully_hinted.rs b/tests/compile-fail/inference_fully_hinted.rs index bee4328b85..645d1572a2 100644 --- a/tests/compile-fail/inference_fully_hinted.rs +++ b/tests/compile-fail/inference_fully_hinted.rs @@ -8,11 +8,11 @@ use nickel::{Nickel, HttpRouter, Request, Response}; fn main() { let mut server = Nickel::new(); - server.utilize(|_: &mut Request, res: Response| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/com + server.utilize(|_: &mut Request<()>, res: Response<()>| res.send("Hello World!")); + //~^ ERROR type mismatch resolving `for<' - server.get("**", |_: &mut Request, res: Response| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/com + server.get("**", |_: &mut Request<()>, res: Response<()>| res.send("Hello World!")); + //~^ ERROR type mismatch resolving `for<' server.listen("127.0.0.1:6767"); } diff --git a/tests/compile-fail/inference_no_hints.rs b/tests/compile-fail/inference_no_hints.rs index 5b4780d7c9..f524af5a23 100644 --- a/tests/compile-fail/inference_no_hints.rs +++ b/tests/compile-fail/inference_no_hints.rs @@ -9,14 +9,14 @@ fn main() { let mut server = Nickel::new(); server.utilize(|_, res| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/compile-fail + //~^ ERROR type mismatch resolving `for<' //~^^ ERROR the type of this value must be known in this context - //~^^^ ERROR type mismatch: the type `[closure tests/compile + //~^^^ ERROR type mismatch: the type `[closure@tests/compile server.get("**", |_, res| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/compile-fail + //~^ ERROR type mismatch resolving `for<' //~^^ ERROR the type of this value must be known in this context - //~^^^ ERROR type mismatch: the type `[closure tests/compile + //~^^^ ERROR type mismatch: the type `[closure@tests/compile server.listen("127.0.0.1:6767"); } diff --git a/tests/compile-fail/inference_request_hinted.rs b/tests/compile-fail/inference_request_hinted.rs index 1b46b5e098..b6c6d96cc3 100644 --- a/tests/compile-fail/inference_request_hinted.rs +++ b/tests/compile-fail/inference_request_hinted.rs @@ -9,13 +9,13 @@ fn main() { let mut server = Nickel::new(); // Request hinted - server.utilize(|_: &mut Request, res| res.send("Hello World!")); + server.utilize(|_: &mut Request<()>, res| res.send("Hello World!")); //~^ ERROR the type of this value must be known in this context - //~^^ ERROR type mismatch resolving `for<'r,'b,'a> + //~^^ ERROR type mismatch resolving `for<' - server.get("**", |_: &mut Request, res| res.send("Hello World!")); + server.get("**", |_: &mut Request<()>, res| res.send("Hello World!")); //~^ ERROR the type of this value must be known in this context - //~^^ ERROR type mismatch resolving `for<'r,'b,'a> + //~^^ ERROR type mismatch resolving `for<' server.listen("127.0.0.1:6767"); } diff --git a/tests/compile-fail/inference_response_hinted.rs b/tests/compile-fail/inference_response_hinted.rs index 6b8f07e36c..a7c9431afb 100644 --- a/tests/compile-fail/inference_response_hinted.rs +++ b/tests/compile-fail/inference_response_hinted.rs @@ -8,13 +8,13 @@ use nickel::{Nickel, HttpRouter, Request, Response}; fn main() { let mut server = Nickel::new(); - server.utilize(|_, res: Response| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/compile-fail - //~^^ ERROR type mismatch: the type `[closure tests/compile-fail + server.utilize(|_, res: Response<()>| res.send("Hello World!")); + //~^ ERROR type mismatch resolving `for<' + //~^^ ERROR type mismatch: the type `[closure@tests/compile-fail - server.get("**", |_, res: Response| res.send("Hello World!")); - //~^ ERROR type mismatch resolving `for<'r,'b,'a> <[closure tests/compile-fail - //~^^ ERROR type mismatch: the type `[closure tests/compile-fail + server.get("**", |_, res: Response<()>| res.send("Hello World!")); + //~^ ERROR type mismatch resolving `for<' + //~^^ ERROR type mismatch: the type `[closure@tests/compile-fail server.listen("127.0.0.1:6767"); } From fc35544ccc5f672285e77ef731df520498994126 Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Mon, 7 Sep 2015 17:13:10 +0100 Subject: [PATCH 4/4] fix(middleware): satisfy lifetime requirements for RFC 1214 --- src/middleware.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/middleware.rs b/src/middleware.rs index d373f11753..1e9cbcb1e6 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -32,7 +32,7 @@ pub trait ErrorHandler: Send + 'static + Sync { fn handle_error(&self, &mut NickelError, &mut Request) -> Action; } -impl ErrorHandler for fn(&mut NickelError, &mut Request) -> Action { +impl ErrorHandler for fn(&mut NickelError, &mut Request) -> Action { fn handle_error(&self, err: &mut NickelError, req: &mut Request) -> Action { (*self)(err, req) } @@ -43,7 +43,7 @@ pub struct MiddlewareStack { error_handlers: Vec + Send + Sync>> } -impl MiddlewareStack { +impl MiddlewareStack { pub fn add_middleware> (&mut self, handler: T) { self.handlers.push(Box::new(handler)); }