Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Response API and trim NickelError #170

Merged
merged 8 commits into from
Mar 24, 2015
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ Then try `localhost:6767/user/4711` and `localhost:6767/bar`
Here is how sample server in `example.rs` looks like:

```rust
#![feature(core, io, net)]
#![feature(core, net)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate nickel;
#[macro_use] extern crate nickel_macros;

use nickel::status::StatusCode::{self, NotFound, BadRequest};
use nickel::{
Nickel, NickelError, ErrorWithStatusCode, Continue, Halt, Request,
Nickel, NickelError, Continue, Halt, Request,
QueryString, JsonBody, StaticFilesHandler, HttpRouter, Action
};
use std::net::IpAddr;
Expand Down Expand Up @@ -155,21 +155,17 @@ fn main() {

//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 {
match err.kind {
ErrorWithStatusCode(NotFound) => {
// FIXME: Supportable?
// response.content_type(MediaType::Html)
// .status_code(NotFound)
// .send("<h1>Call the police!<h1>");
if let Some(ref mut res) = err.stream {
let _ = res.write_all(b"<h1>Call the police!</h1>");
}
Halt(())
},
_ => Continue(())
if let Some(ref mut res) = err.stream {
if let NotFound = res.status() {
let _ = res.write_all(b"<h1>Call the police!</h1>");
return Halt(())
}
}

Continue(())
}


// issue #20178
let custom_handler: fn(&mut NickelError, &mut Request) -> Action = custom_404;

Expand Down
28 changes: 12 additions & 16 deletions examples/example.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#![feature(core, io, net)]
#![feature(core)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate nickel;
#[macro_use] extern crate nickel_macros;

use nickel::status::StatusCode::{self, NotFound, BadRequest};
use nickel::{
Nickel, NickelError, ErrorWithStatusCode, Continue, Halt, Request,
Nickel, NickelError, Continue, Halt, Request,
QueryString, JsonBody, StaticFilesHandler, HttpRouter, Action
};
use std::net::IpAddr;

use std::collections::BTreeMap;
use std::io::Write;
use rustc_serialize::json::{Json, ToJson};
Expand Down Expand Up @@ -100,25 +100,21 @@ fn main() {

//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 {
match err.kind {
ErrorWithStatusCode(NotFound) => {
// FIXME: Supportable?
// response.content_type(MediaType::Html)
// .status_code(NotFound)
// .send("<h1>Call the police!<h1>");
if let Some(ref mut res) = err.stream {
let _ = res.write_all(b"<h1>Call the police!</h1>");
}
Halt(())
},
_ => Continue(())
if let Some(ref mut res) = err.stream {
if res.status() == NotFound {
let _ = res.write_all(b"<h1>Call the police!</h1>");
return Halt(())
}
}

Continue(())
}


// issue #20178
let custom_handler: fn(&mut NickelError, &mut Request) -> Action = custom_404;

server.handle_error(custom_handler);

server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
10 changes: 3 additions & 7 deletions examples/example_route_data.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#![feature(net)]

extern crate nickel;

use nickel::{Nickel, Request, Response, HttpRouter, MiddlewareResult, Halt};
use std::net::IpAddr;
use nickel::{Nickel, Request, Response, HttpRouter, MiddlewareResult};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;

Expand All @@ -17,13 +14,12 @@ fn main() {
fn root_handler<'a>(_: &mut Request, response: Response<'a>, logger: &Logger)
-> MiddlewareResult<'a> {
let text = format!("{}", logger.visits.fetch_add(1, Relaxed));
let response = try!(response.send(text));
Ok(Halt(response))
response.send(text)
}

// issue #20178
let rhandler: for <'a> fn(&mut Request, Response<'a>, &Logger) -> MiddlewareResult<'a> = root_handler;

server.get("/", (rhandler, Logger{visits: AtomicUsize::new(0)}));
server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
8 changes: 3 additions & 5 deletions examples/example_template.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#![feature(net)]
extern crate nickel;
#[macro_use] extern crate nickel_macros;

use nickel::{Nickel, Request, Response, HttpRouter, MiddlewareResult, Halt};
use std::net::IpAddr;
use nickel::{Nickel, Request, Response, HttpRouter, MiddlewareResult};
use std::collections::HashMap;

fn main() {
Expand All @@ -12,10 +10,10 @@ fn main() {
fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> {
let mut data = HashMap::<&str, &str>::new();
data.insert("name", "user");
Ok(Halt(try!(res.render("examples/assets/template.tpl", &data))))
res.render("examples/assets/template.tpl", &data)
}

server.get("/", middleware!(@handler));

server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
4 changes: 1 addition & 3 deletions examples/example_with_default_router.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#![feature(net)]
extern crate nickel;
#[macro_use] extern crate nickel_macros;

use nickel::{Nickel, HttpRouter};
use std::net::IpAddr;

fn main() {
let mut server = Nickel::new();
Expand All @@ -16,5 +14,5 @@ fn main() {
format!("Foo is '{}'", request.param("foo"))
});

server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
4 changes: 1 addition & 3 deletions examples/hello_world.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#![feature(plugin, net)]
#[macro_use] extern crate nickel_macros;
extern crate nickel;

use nickel::Nickel;
use std::net::IpAddr;

fn main() {
let mut server = Nickel::new();
Expand All @@ -14,5 +12,5 @@ fn main() {
}
});

server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
26 changes: 10 additions & 16 deletions examples/macro_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(plugin, core, io, net)]
#![feature(core)]

extern crate url;
extern crate nickel;
Expand All @@ -7,11 +7,10 @@ extern crate "rustc-serialize" as rustc_serialize;

use nickel::status::StatusCode::{self, NotFound};
use nickel::{
Nickel, NickelError, ErrorWithStatusCode, Continue, Halt, Request, Response,
Nickel, NickelError, Continue, Halt, Request, Response,
QueryString, JsonBody, StaticFilesHandler, MiddlewareResult, HttpRouter, Action
};
use std::io::Write;
use std::net::IpAddr;

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
Expand All @@ -27,19 +26,14 @@ fn logger<'a>(request: &mut Request, response: Response<'a>) -> MiddlewareResult

//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 {
match err.kind {
ErrorWithStatusCode(NotFound) => {
// FIXME: Supportable?
// response.content_type(MediaType::Html)
// .status_code(NotFound)
// .send("<h1>Call the police!<h1>");
if let Some(ref mut res) = err.stream {
let _ = res.write_all(b"<h1>Call the police!</h1>");
}
Halt(())
},
_ => Continue(())
if let Some(ref mut res) = err.stream {
if res.status() == NotFound {
let _ = res.write_all(b"<h1>Call the police!</h1>");
return Halt(())
}
}

Continue(())
}

fn main() {
Expand Down Expand Up @@ -118,5 +112,5 @@ fn main() {
server.handle_error(custom_handler);

println!("Running server!");
server.listen(IpAddr::new_v4(127, 0, 0, 1), 6767);
server.listen("127.0.0.1:6767");
}
19 changes: 19 additions & 0 deletions src/as_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}

impl<'a> AsBytes for &'a str {
fn as_bytes(&self) -> &[u8] { str::as_bytes(*self) }
}

impl<'a> AsBytes for &'a [u8] {
fn as_bytes(&self) -> &[u8] { self }
}

impl AsBytes for String {
fn as_bytes(&self) -> &[u8] { self[..].as_bytes() }
}

impl AsBytes for Vec<u8> {
fn as_bytes(&self) -> &[u8] { &self[..] }
}
10 changes: 6 additions & 4 deletions src/default_error_handler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use hyper::status::StatusCode::{NotFound, BadRequest};
use request::Request;
use middleware::{ErrorHandler, Action, Halt};
use nickel_error::{NickelError, ErrorWithStatusCode};
use nickel_error::NickelError;
use std::io::Write;

#[derive(Clone, Copy)]
Expand All @@ -10,13 +10,15 @@ pub struct DefaultErrorHandler;
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 = match err.kind {
ErrorWithStatusCode(NotFound) => b"Not Found",
ErrorWithStatusCode(BadRequest) => b"Bad Request",
let msg : &[u8] = match res.status() {
NotFound => b"Not Found",
BadRequest => b"Bad Request",
_ => b"Internal Server Error"
};

let _ = res.write_all(msg);
} else {
println!("Error: {}", err.message);
}

Halt(())
Expand Down
17 changes: 7 additions & 10 deletions src/favicon_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use hyper::net;

use request::Request;
use response::Response;
use middleware::{Halt, Continue, Middleware, MiddlewareResult};
use middleware::{Continue, Middleware, MiddlewareResult};
use mimes::MediaType;

pub struct FaviconHandler {
Expand All @@ -19,7 +19,7 @@ pub struct FaviconHandler {
}

impl Middleware for FaviconHandler {
fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a>, res: Response<'a, net::Fresh>)
fn invoke<'a, 'b>(&'a self, req: &mut Request<'b, 'a, 'b>, res: Response<'a, net::Fresh>)
-> MiddlewareResult<'a> {
if FaviconHandler::is_favicon_request(req) {
self.handle_request(req, res)
Expand Down Expand Up @@ -66,24 +66,21 @@ impl FaviconHandler {
self.send_favicon(req, res)
},
Options => {
res.status_code(StatusCode::Ok);
res.set_status(StatusCode::Ok);
res.origin.headers_mut().set(header::Allow(vec!(Get, Head, Options)));
let stream = try!(res.send(""));
Ok(Halt(stream))
res.send("")
},
_ => {
res.status_code(StatusCode::MethodNotAllowed);
res.set_status(StatusCode::MethodNotAllowed);
res.origin.headers_mut().set(header::Allow(vec!(Get, Head, Options)));
let stream = try!(res.send(""));
Ok(Halt(stream))
res.send("")
}
}
}

pub fn send_favicon<'a, 'b>(&self, req: &Request, mut res: Response<'a>) -> MiddlewareResult<'a> {
debug!("{:?} {:?}", req.origin.method, self.icon_path.display());
res.content_type(MediaType::Ico);
let stream = try!(res.send(&*self.icon));
Ok(Halt(stream))
res.send(&*self.icon)
}
}
4 changes: 2 additions & 2 deletions src/json_body_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::io::{Read, ErrorKind};
// Plugin boilerplate
struct JsonBodyParser;
impl Key for JsonBodyParser { type Value = String; }
impl<'a, 'b> Plugin<Request<'a, 'b>> for JsonBodyParser {
impl<'a, 'b, 'k> Plugin<Request<'a, 'b, 'k>> for JsonBodyParser {
type Error = io::Error;

fn eval(req: &mut Request) -> io::Result<String> {
Expand All @@ -22,7 +22,7 @@ pub trait JsonBody {
fn json_as<T: Decodable>(&mut self) -> io::Result<T>;
}

impl<'a, 'b> JsonBody for Request<'a, 'b> {
impl<'a, 'b, 'k> JsonBody for Request<'a, 'b, 'k> {
fn json_as<T: Decodable>(&mut self) -> io::Result<T> {
self.get::<JsonBodyParser>().and_then(|parsed|
json::decode::<T>(&*parsed).map_err(|err|
Expand Down
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![crate_name = "nickel"]
#![crate_type = "rlib"]
#![feature(plugin, core, collections, io, net, path, path_ext, std_misc, old_path)]
#![feature(plugin, core, io, path_ext, std_misc)]
#![plugin(regex_macros)]

//!Nickel is supposed to be a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework for JavaScript.
Expand Down Expand Up @@ -37,10 +37,12 @@ pub use default_error_handler::DefaultErrorHandler;
pub use json_body_parser::JsonBody;
pub use query_string::QueryString;
pub use router::{Router, Route, RouteResult, HttpRouter};
pub use nickel_error::{ NickelError, NickelErrorKind, ErrorWithStatusCode, UserDefinedError, Other };
pub use mimes::get_media_type;
pub use nickel_error::NickelError;
pub use mimes::{get_media_type, MediaType};
pub use middleware_handler::ResponseFinalizer;
pub use as_bytes::AsBytes;

mod as_bytes;
pub mod router;
mod server;
mod nickel;
Expand Down
Loading