From f829a84545b9f280534762a6b195bf521003a948 Mon Sep 17 00:00:00 2001 From: Jeff Olhoeft Date: Sun, 19 Nov 2017 15:00:44 -0800 Subject: [PATCH] fix(examples): Fix examples triggering issue #399 Fix the examples that were returning MiddlewareResults in the middlware! macro. A couple could be changed to return a Responder, but most needed to be reimplemented as seperate functions. Updated the middleware! macro documentaion to note the limitations from issues #399 and #389. Disable ssl testing in travis, which was broken in commit 8d5a7d0515dab850d88249f392db8db463437068. Issue #415 to track our SSL plan. --- .travis.yml | 1 - examples/form_data/form_data.rs | 42 +++++++++++++++++--------------- examples/hello_world.rs | 2 +- examples/integration_testing.rs | 12 +++++---- examples/macro_example.rs | 2 +- examples/no_macro_custom_data.rs | 4 +-- examples/static_files.rs | 2 +- examples/template.rs | 18 +++++++------- src/body_parser.rs | 2 +- src/extensions/request.rs | 14 ++++++----- src/extensions/response.rs | 14 +++++++---- src/macros/middleware.rs | 13 ++++++++++ src/query_string.rs | 2 +- src/response.rs | 2 +- src/urlencoded.rs | 2 +- 15 files changed, 78 insertions(+), 54 deletions(-) diff --git a/.travis.yml b/.travis.yml index db9cd8ebfe..dec181fc9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,5 +38,4 @@ env: global: secure: nPXTdkq9TK4LmqJWqB4jxscDG1mnqJzO0UX5ni+oC0SohjgBxdWjbvJ8Kthk3c8Qg/2zGlCryuT1lV4TcD3jF86MHlRlXsO3G8fCbEGdLLzppbV0A2VnEw1knhv2mfUhxA8hsFJE2ncT5qeOVyQ6N3PAMGoYkdhhbD9N/9EWuqs= matrix: - - FEATURES="--features ssl" - FEATURES="" diff --git a/examples/form_data/form_data.rs b/examples/form_data/form_data.rs index a52fe07c99..fb4130dbf7 100644 --- a/examples/form_data/form_data.rs +++ b/examples/form_data/form_data.rs @@ -1,30 +1,34 @@ #[macro_use] extern crate nickel; -use nickel::{Nickel, HttpRouter, FormBody}; +use nickel::{Nickel, HttpRouter, FormBody, Request, Response, MiddlewareResult}; use std::collections::HashMap; -fn main() { - let mut server = Nickel::new(); +fn root<'mw, 'conn>(_req: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { + let mut data = HashMap::new(); + data.insert("title","Contact"); + + return res.render("examples/form_data/views/contact.html", &data) +} - server.get("/", middleware! { |_, res| - let mut data = HashMap::new(); - data.insert("title","Contact"); +fn confirmation<'mw, 'conn>(req: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { + let form_data = try_with!(res, req.form_body()); - return res.render("examples/form_data/views/contact.html", &data) - }); + println!("{:?}", form_data); - server.post("/confirmation", middleware!{ |req, res| - let form_data = try_with!(res, req.form_body()); + let mut data = HashMap::new(); + data.insert("title", "Confirmation"); + data.insert("firstname", form_data.get("firstname").unwrap_or("First name?")); + data.insert("lastname", form_data.get("lastname").unwrap_or("Last name?")); + data.insert("phone", form_data.get("phone").unwrap_or("Phone?")); + data.insert("email", form_data.get("email").unwrap_or("Email?")); + return res.render("examples/form_data/views/confirmation.html", &data) +} + +fn main() { + let mut server = Nickel::new(); - println!("{:?}", form_data); + server.get("/", root); - let mut data = HashMap::new(); - data.insert("title", "Confirmation"); - data.insert("firstname", form_data.get("firstname").unwrap_or("First name?")); - data.insert("lastname", form_data.get("lastname").unwrap_or("Last name?")); - data.insert("phone", form_data.get("phone").unwrap_or("Phone?")); - data.insert("email", form_data.get("email").unwrap_or("Email?")); - return res.render("examples/form_data/views/confirmation.html", &data) - }); + server.post("/confirmation", confirmation); server.listen("0.0.0.0:8080").unwrap(); } diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 73b48025dc..83ae6b7a8f 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -1,4 +1,4 @@ -#[macro_use] extern crate nickel; +extern crate nickel; use nickel::{Nickel, HttpRouter, Request, Response, MiddlewareResult}; diff --git a/examples/integration_testing.rs b/examples/integration_testing.rs index d8bbb2dcbf..af38d02394 100644 --- a/examples/integration_testing.rs +++ b/examples/integration_testing.rs @@ -5,7 +5,7 @@ extern crate nickel; extern crate hyper; extern crate rustc_serialize; -use nickel::{Nickel, ListeningServer, HttpRouter, JsonBody}; +use nickel::{Nickel, ListeningServer, HttpRouter, JsonBody, Request, Response, MiddlewareResult}; use nickel::status::StatusCode; use rustc_serialize::json::Json; @@ -60,6 +60,11 @@ fn main() { start_server(address, database).unwrap(); } +fn log_hit<'mw, 'conn>(_req: &mut Request<'mw, 'conn, ServerData>, res: Response<'mw, ServerData>) -> MiddlewareResult<'mw, ServerData> { + res.data().log_hit(); + return res.next_middleware() +} + fn start_server(address: &str, database: D) -> Result> where D: Database { let server_data = ServerData { @@ -70,10 +75,7 @@ where D: Database { let mut server = Nickel::with_data(server_data); // Track all hits to the server - server.utilize(middleware! { |_req, res| - res.data().log_hit(); - return res.next_middleware() - }); + server.utilize(log_hit); // Core server server.get("/", middleware!( "Hello World" )); diff --git a/examples/macro_example.rs b/examples/macro_example.rs index 5cbcdc6351..bc4d07d94c 100644 --- a/examples/macro_example.rs +++ b/examples/macro_example.rs @@ -7,7 +7,7 @@ use std::io::Write; use nickel::status::StatusCode::{self, NotFound}; use nickel::{ Nickel, NickelError, Continue, Halt, Request, Response, MediaType, - QueryString, JsonBody, StaticFilesHandler, MiddlewareResult, HttpRouter, Action + QueryString, JsonBody, StaticFilesHandler, MiddlewareResult, Action }; use regex::Regex; use hyper::header::Location; diff --git a/examples/no_macro_custom_data.rs b/examples/no_macro_custom_data.rs index 247c5a078c..d1da0a7227 100644 --- a/examples/no_macro_custom_data.rs +++ b/examples/no_macro_custom_data.rs @@ -1,4 +1,4 @@ -#[macro_use] extern crate nickel; +extern crate nickel; use nickel::{Nickel, HttpRouter, Request, Response, MiddlewareResult}; @@ -16,5 +16,5 @@ fn main() { let mut server = Nickel::with_data(my_config); server.get("**", greeter); - server.listen("127.0.0.1:6767"); + server.listen("127.0.0.1:6767").unwrap(); } diff --git a/examples/static_files.rs b/examples/static_files.rs index 4a062d4a6f..ab354cfb0a 100644 --- a/examples/static_files.rs +++ b/examples/static_files.rs @@ -1,4 +1,4 @@ -#[macro_use] extern crate nickel; +extern crate nickel; use nickel::{Nickel, StaticFilesHandler}; diff --git a/examples/template.rs b/examples/template.rs index 0807739eb9..56f92fa089 100644 --- a/examples/template.rs +++ b/examples/template.rs @@ -1,18 +1,18 @@ -#[macro_use] extern crate nickel; +extern crate nickel; -use nickel::{Nickel, HttpRouter}; +use nickel::{Nickel, HttpRouter, Request, Response, MiddlewareResult}; use std::collections::HashMap; +fn render<'mw, 'conn>(_req: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { + let mut data = HashMap::<&str, &str>::new(); + data.insert("name", "user"); + return res.render("examples/assets/template.tpl", &data) +} + fn main() { let mut server = Nickel::new(); - // * NOTE * - // This example is deprecated, you should use nickel_mustache from crates.io - server.get("/", middleware! { |_, res| - let mut data = HashMap::<&str, &str>::new(); - data.insert("name", "user"); - return res.render("examples/assets/template.tpl", &data) - }); + server.get("/", render); server.listen("127.0.0.1:6767").unwrap(); } diff --git a/src/body_parser.rs b/src/body_parser.rs index f30dcd0405..7670eb10a1 100644 --- a/src/body_parser.rs +++ b/src/body_parser.rs @@ -61,7 +61,7 @@ pub trait FormBody { /// let mut server = Nickel::new(); /// server.post("/a", middleware! { |req, res| /// let form_body = try_with!(res, req.form_body()); - /// return res.send(format!("Post: {:?}", form_body)) + /// format!("Post: {:?}", form_body) /// }); /// } /// ``` diff --git a/src/extensions/request.rs b/src/extensions/request.rs index d1c8aacf70..807aa06365 100644 --- a/src/extensions/request.rs +++ b/src/extensions/request.rs @@ -10,17 +10,19 @@ impl<'mw, 'server, D> Referer for Request<'mw, 'server, D> { /// /// # Examples /// ```{rust} - /// #[macro_use] extern crate nickel; + /// extern crate nickel; /// - /// use nickel::{Nickel, HttpRouter}; + /// use nickel::{Nickel, HttpRouter, Request, Response, MiddlewareResult}; /// use nickel::extensions::{Referer, Redirect}; /// + /// fn referer<'mw, 'conn>(req: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { + /// let back = req.referer().unwrap_or("http://nickel-org.github.io/"); + /// return res.redirect(back) + /// } + /// /// fn main() { /// let mut server = Nickel::new(); - /// server.get("/a", middleware! { |req, res| - /// let back = req.referer().unwrap_or("http://nickel.rs"); - /// return res.redirect(back) - /// }); + /// server.get("/a", referer); /// } /// ``` fn referer(&self) -> Option<&str> { diff --git a/src/extensions/response.rs b/src/extensions/response.rs index 71324122e8..76aa7de69b 100644 --- a/src/extensions/response.rs +++ b/src/extensions/response.rs @@ -9,16 +9,18 @@ pub trait Redirect: Sized { /// /// # Examples /// ```{rust} - /// #[macro_use] extern crate nickel; + /// extern crate nickel; /// - /// use nickel::{Nickel, HttpRouter}; + /// use nickel::{Nickel, HttpRouter, Request, Response, MiddlewareResult}; /// use nickel::extensions::Redirect; /// + /// fn redirect<'mw, 'conn>(_: &mut Request<'mw, 'conn>, res: Response<'mw>) -> MiddlewareResult<'mw> { + /// return res.redirect("http://nickel.rs") + /// } + /// /// fn main() { /// let mut server = Nickel::new(); - /// server.get("/a", middleware! { |_, res| - /// return res.redirect("http://nickel.rs") - /// }); + /// server.get("/a", redirect); /// } /// ``` fn redirect(self, target: T) -> Self::Result @@ -35,6 +37,8 @@ pub trait Redirect: Sized { where T: Into; } +// Todo: rework this to return a Responder so it will work with the +// middleware macro impl<'a, D> Redirect for Response<'a, D> { type Result = MiddlewareResult<'a, D>; diff --git a/src/macros/middleware.rs b/src/macros/middleware.rs index 50bfa0820b..6d405829e1 100644 --- a/src/macros/middleware.rs +++ b/src/macros/middleware.rs @@ -4,6 +4,19 @@ /// In future, the macro should hopefully be able to be removed while /// having minimal changes to the closure's code. /// +/// # Limitations +/// +/// The body of the `middleware!` macro needs to return something +/// implementing `Responder`. Some older examples had bodies that +/// would return a `MiddlewareResult`, but this was exploiting an +/// unsoundness in the Rust compiler that has since been +/// tightened. See discussion at +/// https://github.com/nickel-org/nickel.rs/issues/399. +/// +/// Due to the way the macro is expanded, exiting the body early with +/// a return statement will most likely fail with a cryptic error +/// message. See https://github.com/nickel-org/nickel.rs/issues/389. +/// /// # Examples /// ```rust,no_run /// # #[macro_use] extern crate nickel; diff --git a/src/query_string.rs b/src/query_string.rs index a6c8b27f60..86532d1710 100644 --- a/src/query_string.rs +++ b/src/query_string.rs @@ -28,7 +28,7 @@ pub trait QueryString { /// let mut server = Nickel::new(); /// server.get("/a", middleware! { |req, res| /// let query = req.query(); - /// return res.send(format!("Query: {:?}", query)) + /// format!("Query: {:?}", query) /// }); /// } /// ``` diff --git a/src/response.rs b/src/response.rs index 42c82032d6..9ad44541a5 100644 --- a/src/response.rs +++ b/src/response.rs @@ -15,7 +15,7 @@ use time; use mimes::MediaType; use mustache; use mustache::Template; -use std::io::{self, Read, Write, copy}; +use std::io::{self, Write, copy}; use std::fs::File; use std::any::Any; use {NickelError, Halt, MiddlewareResult, Responder, Action}; diff --git a/src/urlencoded.rs b/src/urlencoded.rs index a5bc34b77c..1ed0b445b1 100644 --- a/src/urlencoded.rs +++ b/src/urlencoded.rs @@ -2,7 +2,7 @@ use groupable::Groupable; use hyper::uri::RequestUri; use hyper::uri::RequestUri::{Star, AbsoluteUri, AbsolutePath, Authority}; use std::collections::HashMap; -use url::{form_urlencoded, Url}; +use url::form_urlencoded; type QueryStore = HashMap>;