Repository: rustless/rustless (language: rust)

Issue:
compilation failure: method `call` is not a member of trait `Handler`
```
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:52:5: 61:6 error: method `call` is not a member of trait `Handler`
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:52     fn call(&self, req: &mut iron::Request) -> iron::IronResult<iron::Response> {
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:53         self.call_with_not_found(req).map(|resp| {
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:54             iron::Response {
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:55                 status: Some(resp.status),
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:56                 headers: resp.headers,
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/backend/iron.rs:57                 body: resp.body,
                                                                                                ...
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/batteries/cookie.rs:39:39: 39:54 error: use of undeclared type name `header::Cookies`
/home/xav/.cargo/registry/src/github.com-1ecc6299db9ec823/rustless-0.3.0/src/batteries/cookie.rs:39         let jar = req.headers().get::<header::Cookies>()
```



Discussion / hints:
@bestouff yes, there were some breaking changes in [Iron](https://github.com/iron/iron/pull/275) today. I'll try to address them as soon as possible. I'll let you know.


Fix patch:
diff --git a/examples/simple.rs b/examples/simple.rs
index b5092763..81c26c1e 100644
--- a/examples/simple.rs
+++ b/examples/simple.rs
@@ -1,4 +1,5 @@
-#![allow(unstable)]
+#![feature(core)]
+#![feature(collections)]
 
 #[macro_use]
 extern crate rustless;
@@ -9,10 +10,11 @@ extern crate "rustc-serialize" as serialize;
 extern crate valico;
 extern crate cookie;
 
+use std::fmt;
+use std::error;
+use std::error::Error as StdError;
 use serialize::json;
 
-use iron::{Chain};
-
 use rustless::server::status;
 use rustless::errors::{Error};
 use rustless::batteries::swagger;
@@ -22,12 +24,18 @@ use rustless::{Nesting};
 #[derive(Show, Copy)]
 pub struct UnauthorizedError;
 
-impl std::error::Error for UnauthorizedError {
+impl error::Error for UnauthorizedError {
     fn description(&self) -> &str {
         return "UnauthorizedError";
     }
 }
 
+impl fmt::Display for UnauthorizedError {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        self.description().fmt(formatter)
+    }
+}
+
 fn main() {
 
     let mut app = rustless::Application::new(rustless::Api::build(|api| {
@@ -88,7 +96,10 @@ fn main() {
                 }
 
                 // Fire error from callback is token is wrong
-                return Err(Box::new(UnauthorizedError) as Box<Error>)
+                return Err(rustless::ErrorResponse{
+                    error: Box::new(UnauthorizedError) as Box<Error>,
+                    response: None
+                })
 
             });
 
@@ -129,7 +140,7 @@ fn main() {
         ..std::default::Default::default()
     });
 
-    let mut chain = iron::ChainBuilder::new(app);
+    let mut chain = iron::Chain::new(app);
     chain.link(::rustless::batteries::cookie::new("secretsecretsecretsecretsecretsecretsecret".as_bytes()));
 
     iron::Iron::new(chain).listen("localhost:4000").unwrap();
diff --git a/src/backend/iron.rs b/src/backend/iron.rs
index 2c2666eb..ad99d9d9 100644
--- a/src/backend/iron.rs
+++ b/src/backend/iron.rs
@@ -1,18 +1,24 @@
 use url;
-use std::io::net::ip;
+use std::old_io::net::ip;
 use plugin::{Extensible};
 pub use iron::{Url, Handler};
 
 use iron::{self};
 
 use backend::{self};
-use framework::Application;
+use super::super::framework;
 
 use server::method;
 use server::header;
 
-pub type HandleResult<T> = iron::IronResult<T>;
-pub type HandleSuccessResult = iron::IronResult<()>;
+use super::request;
+use super::super::errors;
+
+pub type HandleResultStrict<T> = Result<T, errors::StrictErrorResponse>;
+pub type HandleResult<T> = Result<T, errors::ErrorResponse>;
+pub type HandleSuccessResult = HandleResult<()>;
+
+impl<'a> request::Body for iron::request::Body<'a> { }
 
 pub trait WrapUrl {
     fn wrap_url(self) -> Url;
@@ -35,28 +41,42 @@ impl backend::AsUrl for Url {
     fn fragment(&self) -> &Option<String> { &self.fragment }
 }
 
-impl backend::Request for iron::Request {
+impl<'a> backend::Request for iron::Request<'a> {
     fn remote_addr(&self) -> &ip::SocketAddr { &self.remote_addr }
     fn headers(&self) -> &header::Headers { &self.headers }
     fn method(&self) -> &method::Method { &self.method }
     fn url(&self) -> &backend::AsUrl { &self.url }
-    fn body(&self) -> &Vec<u8> { &self.body }
+    fn body(&self) -> &request::Body { &self.body }
+    fn body_mut(&mut self) -> &mut request::Body { &mut self.body }
 }
 
-impl ::Extensible for iron::Request {
+impl<'a>  ::Extensible for iron::Request<'a> {
     fn ext(&self) -> &::typemap::TypeMap { self.extensions() }
     fn ext_mut(&mut self) -> &mut ::typemap::TypeMap { self.extensions_mut() }
 }
 
-impl Handler for Application {
-    fn call(&self, req: &mut iron::Request) -> iron::IronResult<iron::Response> {
-        self.call_with_not_found(req).map(|resp| {
-            iron::Response {
-                status: Some(resp.status),
-                headers: resp.headers,
-                body: resp.body,
-                extensions: resp.ext
-            }
-        })
+impl Handler for framework::Application {
+    fn handle<'a>(&self, req: &mut iron::Request<'a>) -> iron::IronResult<iron::Response> {
+        self.call(req)
+            .map(|resp| {
+                iron::Response {
+                    status: Some(resp.status),
+                    headers: resp.headers,
+                    body: resp.body,
+                    extensions: resp.ext
+                }
+            })
+            .map_err(|err_resp| {
+                let errors::StrictErrorResponse{error, response} = err_resp;
+                iron::IronError {
+                    error: error,
+                    response: iron::Response {
+                        status: Some(response.status),
+                        headers: response.headers,
+                        body: response.body,
+                        extensions: response.ext
+                    }
+                }
+            })
     }
 }
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index ae94b3a7..188dd4bb 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -7,6 +7,7 @@ pub use self::iron::{
     Handler, 
     HandleResult, 
     HandleSuccessResult, 
+    HandleResultStrict,
     WrapUrl
 };
 
diff --git a/src/backend/request.rs b/src/backend/request.rs
index cee22835..2c02e0e3 100644
--- a/src/backend/request.rs
+++ b/src/backend/request.rs
@@ -1,5 +1,5 @@
 use std::fmt;
-use std::io::net::ip;
+use std::old_io::net::ip;
 use url;
 
 use framework::media;
@@ -7,6 +7,10 @@ use framework::media;
 use server::method;
 use server::header;
 
+pub trait Body: Reader { }
+
+impl Body for Box<Reader + 'static> { }
+
 pub trait AsUrl {
     fn scheme(&self) -> &str;
     fn host(&self) -> &url::Host;
@@ -18,12 +22,13 @@ pub trait AsUrl {
     fn fragment(&self) -> &Option<String>;
 }
 
-pub trait Request: fmt::Show + Send + ::Extensible {
+pub trait Request: fmt::Debug + ::Extensible {
     fn remote_addr(&self) -> &ip::SocketAddr;
     fn headers(&self) -> &header::Headers;
     fn method(&self) -> &method::Method;
     fn url(&self) -> &AsUrl;
-    fn body(&self) -> &Vec<u8>;
+    fn body(&self) -> &Body;
+    fn body_mut(&mut self) -> &mut Body;
 
     fn is_json_body(&self) -> bool {
         self.headers().get::<header::ContentType>().map_or(false, |ct| media::is_json(&ct.0))
@@ -33,7 +38,6 @@ pub trait Request: fmt::Show + Send + ::Extensible {
         self.headers().get::<header::ContentType>().map_or(false, |ct| media::is_urlencoded(&ct.0))
     }
 
-
     fn is_form_data_body(&self) -> bool {
         self.headers().get::<header::ContentType>().map_or(false, |ct| media::is_form_data(&ct.0))
     }
diff --git a/src/backend/response.rs b/src/backend/response.rs
index a76d0616..362bb601 100644
--- a/src/backend/response.rs
+++ b/src/backend/response.rs
@@ -1,4 +1,4 @@
-use std::io;
+use std::old_io;
 use serialize::json;
 
 use server::header;
@@ -9,7 +9,7 @@ use typemap;
 pub struct Response {
     pub status: status::StatusCode,
     pub headers: header::Headers,
-    pub body: Option<Box<io::Reader + Send>>,
+    pub body: Option<Box<old_io::Reader + Send>>,
     pub ext: typemap::TypeMap
 }
 
@@ -25,7 +25,7 @@ impl Response {
     }
 
     #[allow(dead_code)]
-    pub fn from_reader(status: status::StatusCode, body: Box<io::Reader + Send>) -> Response {
+    pub fn from_reader(status: status::StatusCode, body: Box<old_io::Reader + Send>) -> Response {
         Response {
             status: status,
             headers: header::Headers::new(),
@@ -58,18 +58,18 @@ impl Response {
     }
 
     pub fn push_string(&mut self, body: String) {
-        self.body = Some(Box::new(io::MemReader::new(body.into_bytes())) as Box<io::Reader + Send>)
+        self.body = Some(Box::new(old_io::MemReader::new(body.into_bytes())) as Box<old_io::Reader + Send>)
     }
 
-    pub fn push_file(&mut self, path: &Path) -> io::IoResult<()> {
-        let reader = Box::new(try!(io::File::open(path)));
-        self.body = Some(reader as Box<io::Reader + Send>);
+    pub fn push_file(&mut self, path: &Path) -> old_io::IoResult<()> {
+        let reader = Box::new(try!(old_io::File::open(path)));
+        self.body = Some(reader as Box<old_io::Reader + Send>);
 
         Ok(())
     }
 
     #[allow(dead_code)]
-    pub fn from_file(path: &Path) -> io::IoResult<Response> {
+    pub fn from_file(path: &Path) -> old_io::IoResult<Response> {
         let mut response = Response::new(status::StatusCode::Ok);
         try!(response.push_file(path));
         Ok(response)
@@ -80,7 +80,7 @@ impl Response {
 impl_extensible!(Response);
 
 impl Reader for Response {
-    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<usize> {
+    fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult<usize> {
         match self.body {
             Some(ref mut reader) => reader.read(buf),
             None => Ok(0us)
diff --git a/src/backend/simple_request.rs b/src/backend/simple_request.rs
index dc126394..f7ec0ab9 100644
--- a/src/backend/simple_request.rs
+++ b/src/backend/simple_request.rs
@@ -1,12 +1,13 @@
-use std::io;
+use std::old_io;
 use std::fmt;
-use std::io::net::ip;
+use std::old_io::net::ip;
 use typemap;
 
 use {Extensible};
 
 use server::method;
 use server::header;
+use super::request;
 use backend::{Request, Url, AsUrl, WrapUrl};
 
 #[allow(dead_code)]
@@ -16,10 +17,10 @@ pub struct SimpleRequest {
     pub remote_addr: ip::SocketAddr,
     pub headers: header::Headers,
     pub method: method::Method,
-    pub body: Vec<u8>
+    pub body: Box<Reader + 'static>
 }
 
-impl Request for SimpleRequest {
+impl<'a> Request for SimpleRequest {
 
     fn url(&self) -> &AsUrl {
         return &self.url;    
@@ -37,10 +38,14 @@ impl Request for SimpleRequest {
         return &self.method;
     }
 
-    fn body(&self) -> &Vec<u8> {
+    fn body(&self) -> &request::Body {
         return &self.body;
     }
 
+    fn body_mut(&mut self) -> &mut request::Body {
+        return &mut self.body;
+    }
+
 }
 
 #[allow(dead_code)]
@@ -53,7 +58,7 @@ impl SimpleRequest {
             ext: typemap::TypeMap::new(),
             remote_addr: "127.0.0.1:8000".parse().unwrap(),
             headers: header::Headers::new(),
-            body: vec![]
+            body: Box::new(old_io::MemReader::new(vec![]))
         }
     }
 
@@ -78,12 +83,11 @@ impl SimpleRequest {
     }
 
     pub fn push_string(&mut self, body: String) {
-        self.body = body.into_bytes()
+        self.body = Box::new(old_io::MemReader::new(body.into_bytes()));
     }
 
-    pub fn push_file(&mut self, path: &Path) -> io::IoResult<()> {
-        let mut reader = Box::new(try!(io::File::open(path)));
-        self.body = try!(reader.read_to_end());
+    pub fn push_file(&mut self, path: &Path) -> old_io::IoResult<()> {
+        self.body = Box::new(try!(old_io::File::open(path)));
 
         Ok(())
     }
@@ -92,7 +96,7 @@ impl SimpleRequest {
 
 impl_extensible!(SimpleRequest);
 
-impl fmt::Show for SimpleRequest {
+impl fmt::Debug for SimpleRequest {
     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         try!(writeln!(f, "SimpleRequest ->"));
         try!(writeln!(f, "  url: {}", self.url));
diff --git a/src/batteries/cookie.rs b/src/batteries/cookie.rs
index cc4cf415..b8584969 100644
--- a/src/batteries/cookie.rs
+++ b/src/batteries/cookie.rs
@@ -19,7 +19,7 @@ pub trait CookieExt {
     }
 }
 
-impl CookieExt for backend::Request {
+impl<'r> CookieExt for (backend::Request + 'r) {
     fn find_cookie_jar<'a>(&'a mut self) -> Option<&'a mut cookie::CookieJar<'static>> {
         self.ext_mut().get_mut::<CookieJarKey>()
     }
@@ -36,7 +36,7 @@ pub struct CookieDecodeMiddleware {
 impl iron::BeforeMiddleware for CookieDecodeMiddleware {
     fn before(&self, req: &mut iron::Request) -> iron::IronResult<()> {
         let token = self.secret_token.as_slice();
-        let jar = req.headers().get::<header::Cookies>()
+        let jar = req.headers().get::<header::Cookie>()
             .map(|cookies| cookies.to_cookie_jar(token))
             .unwrap_or_else(|| cookie::CookieJar::new(token));
 
@@ -49,7 +49,7 @@ impl iron::BeforeMiddleware for CookieDecodeMiddleware {
 pub struct CookieEncodeMiddleware;
 
 impl iron::AfterMiddleware for CookieEncodeMiddleware {
-    fn after(&self, req: &mut iron::Request, res: &mut iron::Response) -> iron::IronResult<()> {
+    fn after(&self, req: &mut iron::Request, mut res: iron::Response) -> iron::IronResult<iron::Response> {
         let maybe_jar = (req as &mut backend::Request).find_cookie_jar();
         match maybe_jar {
             Some(jar) => {
@@ -58,7 +58,7 @@ impl iron::AfterMiddleware for CookieEncodeMiddleware {
             None => ()
         }
 
-        Ok(())
+        Ok(res)
     }
 }
 
diff --git a/src/batteries/swagger.rs b/src/batteries/swagger.rs
index 63158d5f..26a80f40 100644
--- a/src/batteries/swagger.rs
+++ b/src/batteries/swagger.rs
@@ -183,7 +183,7 @@ struct Param {
 
 impl json::ToJson for Param {
     fn to_json(&self) -> json::Json {
-        jsonway::JsonWay::object(|param| {
+        jsonway::object(|param| {
             param.set("name", self.name.clone());
             param.set("in", self.place.to_string());
             if self.description.is_some() {
@@ -218,7 +218,7 @@ pub fn enable(app: &mut framework::Application, spec: Spec) {
 #[allow(unused_variables)]
 /// Build the basic Swagger 2.0 object
 pub fn build_spec(app: &framework::Application, spec: Spec) -> json::Json {
-    jsonway::JsonWay::object(|&: json| {
+    jsonway::object(|&: json| {
         // Required. Specifies the Swagger Specification version being used. 
         // It can be used by the Swagger UI and other clients to interpret the API listing. 
         // The value MUST be "2.0".
@@ -507,7 +507,7 @@ fn fill_paths<'a>(mut context: WalkContext<'a>, paths: &mut jsonway::ObjectBuild
 #[allow(unused_variables)]
 /// Creates Endpoint definition according to Swagger 2.0 specification
 fn build_endpoint_definition(endpoint: &framework::Endpoint, context: &mut WalkContext) -> json::Json {
-    jsonway::JsonWay::object(|: def| {
+    jsonway::object(|: def| {
         // A list of tags for API documentation control. Tags can be used for logical grouping 
         // of operations by resources or any other qualifier.
         // def.array("tags", |tags| { });
diff --git a/src/errors.rs b/src/errors.rs
index a305e5ca..2aba3169 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -1,47 +1,62 @@
 use serialize::json;
-use std::io;
+use std::old_io;
 pub use error::{Error};
-use std;
+use std::error::Error as StdError;
 
-#[derive(Show, Copy)]
-pub struct NotMatch;
+use super::backend;
 
-impl std::error::Error for NotMatch {
-    fn description(&self) -> &str {
-        return "NotMatch";
-    }
+pub struct ErrorResponse {
+    pub error: Box<Error>,
+    pub response: Option<backend::Response>
 }
 
-#[derive(Show, Copy)]
-pub struct NotFound;
+pub struct StrictErrorResponse {
+    pub error: Box<Error>,
+    pub response: backend::Response
+}
 
-impl std::error::Error for NotFound {
-    fn description(&self) -> &str {
-        return "NotFound";
-    }
+macro_rules! error_response{
+    ($error:expr) => ($crate::errors::ErrorResponse{
+        error: Box::new($error) as Box<$crate::errors::Error>,
+        response: None
+    })
 }
 
-#[derive(Show, Copy)]
-pub struct QueryString;
+macro_rules! impl_basic_err {
+    ($err:ty, $code:expr) => {
+        impl ::std::error::Error for $err {
+            fn description(&self) -> &str {
+                $code
+            }
+        }
 
-impl std::error::Error for QueryString {
-    fn description(&self) -> &str {
-        return "QueryString";
+        impl ::std::fmt::Display for $err {
+            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                self.description().fmt(formatter)
+            }
+        }
     }
 }
 
-#[derive(Show)]
+#[derive(Debug, Copy)]
+pub struct NotMatch;
+impl_basic_err!(NotMatch, "NotMatch");
+
+#[derive(Debug, Copy)]
+pub struct NotFound;
+impl_basic_err!(NotFound, "NotFound");
+
+#[derive(Debug, Copy)]
+pub struct QueryString;
+impl_basic_err!(QueryString, "QueryString");
+
+#[derive(Debug)]
 pub struct Validation {
     pub reason: json::Object
 }
+impl_basic_err!(Validation, "Validation");
 
-impl std::error::Error for Validation {
-    fn description(&self) -> &str {
-        return "Validation";
-    }
-}
-
-#[derive(Show)]
+#[derive(Debug)]
 pub struct Body {
     pub reason: String
 }
@@ -53,27 +68,12 @@ impl Body {
         }
     }
 }
+impl_basic_err!(Body, "Body");
 
-impl std::error::Error for Body {
-    fn description(&self) -> &str {
-        return "Body";
-    }
-}
-
-#[derive(Show)]
-pub struct File(pub io::IoError);
-
-impl std::error::Error for File {
-    fn description(&self) -> &str {
-        let &File(ref error) = self;
-        error.desc
-    }
-}
+#[derive(Debug)]
+pub struct File(pub old_io::IoError);
+impl_basic_err!(File, "File");
 
-#[derive(Show, Copy)]
+#[derive(Debug, Copy)]
 pub struct NotAcceptable;
-impl std::error::Error for NotAcceptable {
-    fn description(&self) -> &str {
-        "NotAcceptable"
-    }
-}
+impl_basic_err!(NotAcceptable, "NotAcceptable");
diff --git a/src/framework/api.rs b/src/framework/api.rs
index 55e3ed29..bc4f9fb7 100644
--- a/src/framework/api.rs
+++ b/src/framework/api.rs
@@ -1,18 +1,13 @@
-use collections;
 use serialize::json;
 
-use queryst;
-
 use backend;
 use server::mime;
 use server::header;
 use errors::{self, Error};
 
 use framework::{self, ApiHandler};
-use framework::app;
 use framework::nesting::{self, Nesting, Node};
 use framework::media;
-use framework::formatters;
 use framework::path;
 
 #[allow(dead_code)]
@@ -39,7 +34,6 @@ pub struct Api {
     after_validation: framework::Callbacks,
     after: framework::Callbacks,
     error_formatters: framework::ErrorFormatters,
-    default_error_formatters: framework::ErrorFormatters,
     consumes: Option<Vec<mime::Mime>>,
     produces: Option<Vec<mime::Mime>>,
 }
@@ -58,7 +52,6 @@ impl Api {
             after_validation: vec![],
             after: vec![],
             error_formatters: vec![],
-            default_error_formatters: vec![formatters::create_default_error_formatter()],
             consumes: None,
             produces: None,
         }
@@ -97,14 +90,7 @@ impl Api {
 
     fn handle_error(&self, err: &Box<Error>, media: &media::Media) -> Option<backend::Response>  {
         for err_formatter in self.error_formatters.iter() {
-            match (*err_formatter)(err, media) {
-                Some(resp) => return Some(resp),
-                None => ()
-            }
-        }
-
-        for err_formatter in self.default_error_formatters.iter() {
-            match (*err_formatter)(err, media) {
+            match err_formatter(err, media) {
                 Some(resp) => return Some(resp),
                 None => ()
             }
@@ -123,130 +109,24 @@ impl Api {
             _ => Some(media::Media::default())
         }
     }
-
-    fn parse_query(query_str: &str, params: &mut json::Object) -> backend::HandleSuccessResult {
-        let maybe_query_params = queryst::parse(query_str);
-        match maybe_query_params {
-            Ok(query_params) => {
-                for (key, value) in query_params.as_object().unwrap().iter() {
-                    if !params.contains_key(key) {
-                        params.insert(key.to_string(), value.clone());
-                    }
-                }
-            }, 
-            Err(_) => {
-                return Err(Box::new(errors::QueryString) as Box<Error>);
-            }
-        }
-
-        Ok(())
-    }
-
-    fn parse_utf8(req: &mut backend::Request) -> backend::HandleResult<String> {
-        match String::from_utf8(req.body().clone()) {
-            Ok(e) => Ok(e),
-            Err(_) => Err(Box::new(
-                errors::Body::new("Invalid UTF-8 sequence".to_string())
-            ) as Box<Error>),
-        }
-    }
-
-    fn parse_json_body(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
-
-        let utf8_string_body = try!(Api::parse_utf8(req));
-
-        if utf8_string_body.len() > 0 {
-          let maybe_json_body = utf8_string_body.parse::<json::Json>();
-            match maybe_json_body {
-                Some(json_body) => {
-                    for (key, value) in json_body.as_object().unwrap().iter() {
-                        if !params.contains_key(key) {
-                            params.insert(key.to_string(), value.clone());
-                        }
-                    }
-                },
-                None => return Err(Box::new(errors::Body::new(format!("Invalid JSON"))) as Box<Error>)
-            }  
-        }
-
-        Ok(())
-    }
-
-    fn parse_urlencoded_body(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
-        let utf8_string_body = try!(Api::parse_utf8(req));
-
-        if utf8_string_body.len() > 0 {
-            let maybe_json_body = queryst::parse(utf8_string_body.as_slice());
-            match maybe_json_body {
-                Ok(json_body) => {
-                    for (key, value) in json_body.as_object().unwrap().iter() {
-                        if !params.contains_key(key) {
-                            params.insert(key.to_string(), value.clone());
-                        }
-                    }
-                },
-                Err(_) => return Err(Box::new(errors::Body::new(format!("Invalid encoded data"))) as Box<Error>)
-            }  
-        }
-
-        Ok(())
-    }
-
-    fn parse_request(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
-        // extend params with query-string params if any
-        if req.url().query().is_some() {
-            try!(Api::parse_query(req.url().query().as_ref().unwrap().as_slice(), params));   
-        }
-
-        // extend params with json-encoded body params if any
-        if req.is_json_body() {
-            try!(Api::parse_json_body(req, params));
-        } else if req.is_urlencoded_body() {
-            try!(Api::parse_urlencoded_body(req, params));
-        }
-
-        Ok(())
-    }
-
-    #[allow(unused_variables)]
-    pub fn call(&self, rest_path: &str, req: &mut backend::Request, app: &app::Application) 
-    -> backend::HandleResult<backend::Response> {
-        let mut params = collections::BTreeMap::new();
-        try!(Api::parse_request(req, &mut params));
-        
-        match self.api_call(rest_path, &mut params, req, &mut framework::CallInfo::new(app))  {
-            Ok(resp) => Ok(resp),
-            Err(err) => {
-                if err.downcast::<errors::NotMatch>().is_none() {
-                    // FIXME: Here we extract mime second time (first time in `api_call`), 
-                    //        maybe we can do something better?
-                    match self.handle_error(&err, &self.extract_media(req).unwrap_or_else(|| media::Media::default())) {
-                        Some(resp) => Ok(resp),
-                        None => Err(err)
-                    }
-                } else {
-                    Err(err)
-                }
-            }
-        }
-    }
-    
 }
 
 impl_nesting!(Api);
 
 impl framework::ApiHandler for Api {
-    fn api_call<'a>(&'a self, rest_path: &str, params: &mut json::Object, 
-                    req: &mut backend::Request, info: &mut framework::CallInfo<'a>) 
-    -> backend::HandleResult<backend::Response> {
-        
+    fn api_call<'a, 'r>(&'a self, 
+        rest_path: &str, 
+        params: &mut json::Object, 
+        req: &'r mut (backend::Request + 'r), 
+        info: &mut framework::CallInfo<'a>) -> backend::HandleResult<backend::Response> {
+
         // Check prefix
         let mut rest_path = match self.prefix.as_ref() {
             Some(prefix) => {
                 if rest_path.starts_with(prefix.as_slice()) {
-                    path::normalize(rest_path.slice_from(prefix.len()))
+                    path::normalize(&rest_path[(prefix.len())..])
                 } else {
-                   return Err(Box::new(errors::NotMatch) as Box<Error>)
+                   return Err(error_response!(errors::NotMatch))
                 }
             },
             None => rest_path
@@ -263,15 +143,15 @@ impl framework::ApiHandler for Api {
             match versioning {
                 &Versioning::Path => {
                     if rest_path.starts_with(version.as_slice()) {
-                        rest_path = path::normalize(rest_path.slice_from(version.len()))
+                        rest_path = path::normalize(&rest_path[(version.len())..])
                     } else {
-                       return Err(Box::new(errors::NotMatch) as Box<Error>)
+                       return Err(error_response!(errors::NotMatch))
                     }
                 },
                 &Versioning::Param(ref param_name) => {
                     match params.get(*param_name) {
                         Some(obj) if obj.is_string() && obj.as_string().unwrap() == version.as_slice() => (),
-                        _ => return Err(Box::new(errors::NotMatch) as Box<Error>)
+                        _ => return Err(error_response!(errors::NotMatch))
                     }
                 },
                 &Versioning::AcceptHeader(ref vendor) => {
@@ -294,12 +174,12 @@ impl framework::ApiHandler for Api {
                             }
 
                             if matched_media.is_none() {
-                                return Err(Box::new(errors::NotMatch) as Box<Error>)
+                                return Err(error_response!(errors::NotMatch))
                             } else {
                                 media = matched_media;
                             }
                         },
-                        None => return Err(Box::new(errors::NotMatch) as Box<Error>)
+                        None => return Err(error_response!(errors::NotMatch))
                     }
                 }
             }
@@ -311,11 +191,21 @@ impl framework::ApiHandler for Api {
                 Some(media) => {
                     info.media = media
                 },
-                None => return Err(Box::new(errors::NotAcceptable) as Box<Error>)
+                None => return Err(error_response!(errors::NotAcceptable))
             }
         }
 
         self.push_node(info);
-        self.call_handlers(rest_path, params, req, info)
+        self.call_handlers(rest_path, params, req, info).map_err(|err_resp| {
+            if err_resp.response.is_some() {
+                err_resp
+            } else {
+                let resp = self.handle_error(&err_resp.error, &self.extract_media(req).unwrap_or_else(|| media::Media::default()));
+                errors::ErrorResponse { 
+                    error: err_resp.error,
+                    response: resp
+                }
+            }
+        })
     }
 }
\ No newline at end of file
diff --git a/src/framework/app.rs b/src/framework/app.rs
index 732761be..99a29cdf 100644
--- a/src/framework/app.rs
+++ b/src/framework/app.rs
@@ -1,8 +1,13 @@
+use std::collections;
+use serialize::json;
 use typemap;
-use framework::api;
-use backend;
-use server::status;
-use errors;
+use queryst;
+
+use super::{ApiHandler};
+use super::api;
+use super::super::backend;
+use super::super::errors;
+use super::super::server::status;
 
 pub struct Application {
     pub ext: typemap::TypeMap,
@@ -19,20 +24,141 @@ impl Application {
         }
     }
 
-    pub fn call(&self, req: &mut backend::Request) -> backend::HandleResult<backend::Response> {
-        self.root_api.call((req.url().path().connect("/").as_slice()).as_slice(), req, self)
+    fn call_internal<'a>(&self, req: &'a mut (backend::Request + 'a)) -> backend::HandleResult<backend::Response> {
+        let mut params = collections::BTreeMap::new();
+        let parse_result = parse_request(req, &mut params);
+
+        parse_result.and_then(|_| {
+            self.root_api.api_call((req.url().path().connect("/").as_slice()).as_slice(), &mut params, req, &mut super::CallInfo::new(self))
+        })
+    }
+
+    pub fn call<'a>(&self, req: &'a mut (backend::Request + 'a)) -> backend::HandleResultStrict<backend::Response> {
+        self.call_internal(req)
+            .map_err(|error_response| {
+                if error_response.response.is_some() {
+                    let errors::ErrorResponse{error, response} = error_response;
+                    errors::StrictErrorResponse{
+                        error: error,
+                        response: response.unwrap()
+                    }
+                } else {
+                    let errors::ErrorResponse{error, ..} = error_response;
+
+                    // Simple default error responses for common errors
+                    let response = if error.is::<errors::NotMatch>() {
+                        backend::Response::new(
+                            status::StatusCode::NotFound
+                        )
+                    } else if error.is::<errors::Validation>() {
+                        backend::Response::new(
+                            status::StatusCode::BadRequest
+                        )
+                    } else {
+                        backend::Response::new(
+                            status::StatusCode::InternalServerError
+                        )
+                    };
+
+                    errors::StrictErrorResponse {
+                        error: error,
+                        response: response
+                    }
+                } 
+            })
     }
+}
 
-    pub fn call_with_not_found(&self, req: &mut backend::Request) -> backend::HandleResult<backend::Response> {
-        let res = self.call(req);
-        match res {
-            Ok(res) => Ok(res),
-            Err(err) => {
-                if err.downcast::<errors::NotMatch>().is_some() {
-                    return Ok(backend::Response::from_string(status::StatusCode::NotFound, "".to_string()));
+fn parse_query(query_str: &str, params: &mut json::Object) -> backend::HandleSuccessResult {
+    let maybe_query_params = queryst::parse(query_str);
+    match maybe_query_params {
+        Ok(query_params) => {
+            for (key, value) in query_params.as_object().unwrap().iter() {
+                if !params.contains_key(key) {
+                    params.insert(key.to_string(), value.clone());
                 }
-                return Err(err);
             }
+        }, 
+        Err(_) => {
+            return Err(error_response!(errors::QueryString));
         }
     }
+
+    Ok(())
+}
+
+fn parse_utf8(req: &mut backend::Request) -> backend::HandleResult<String> {
+    // FIXME https://github.com/rustless/rustless/issues/19
+    //       We need to implement some common Iron middleware/plugin 
+    //       and use it instead of `.read_to_end()`.
+    match req.body_mut().read_to_end() {
+        Ok(bytes) => {
+             match String::from_utf8(bytes) {
+                Ok(e) => Ok(e),
+                Err(_) => Err(error_response!(
+                    errors::Body::new("Invalid UTF-8 sequence".to_string())
+                )),
+            }
+        },
+        Err(_) => Err(error_response!(
+            errors::Body::new("Invalid request body".to_string())
+        )),
+    }
+}
+
+fn parse_json_body(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
+
+    let utf8_string_body = try!(parse_utf8(req));
+
+    if utf8_string_body.len() > 0 {
+      let maybe_json_body = utf8_string_body.parse::<json::Json>();
+        match maybe_json_body {
+            Some(json_body) => {
+                for (key, value) in json_body.as_object().unwrap().iter() {
+                    if !params.contains_key(key) {
+                        params.insert(key.to_string(), value.clone());
+                    }
+                }
+            },
+            None => return Err(error_response!(errors::Body::new(format!("Invalid JSON"))))
+        }  
+    }
+
+    Ok(())
+}
+
+fn parse_urlencoded_body(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
+    let utf8_string_body = try!(parse_utf8(req));
+
+    if utf8_string_body.len() > 0 {
+        let maybe_json_body = queryst::parse(utf8_string_body.as_slice());
+        match maybe_json_body {
+            Ok(json_body) => {
+                for (key, value) in json_body.as_object().unwrap().iter() {
+                    if !params.contains_key(key) {
+                        params.insert(key.to_string(), value.clone());
+                    }
+                }
+            },
+            Err(_) => return Err(error_response!(errors::Body::new(format!("Invalid encoded data"))))
+        }  
+    }
+
+    Ok(())
+}
+
+fn parse_request(req: &mut backend::Request, params: &mut json::Object) -> backend::HandleSuccessResult {
+    // extend params with query-string params if any
+    if req.url().query().is_some() {
+        try!(parse_query(req.url().query().as_ref().unwrap().as_slice(), params));   
+    }
+
+    // extend params with json-encoded body params if any
+    if req.is_json_body() {
+        try!(parse_json_body(req, params));
+    } else if req.is_urlencoded_body() {
+        try!(parse_urlencoded_body(req, params));
+    }
+
+    Ok(())
 }
\ No newline at end of file
diff --git a/src/framework/client.rs b/src/framework/client.rs
index 1973c340..851b1032 100644
--- a/src/framework/client.rs
+++ b/src/framework/client.rs
@@ -14,7 +14,7 @@ use server::header;
 pub struct Client<'a> {
     pub app: &'a app::Application,
     pub endpoint: &'a endpoint::Endpoint,
-    pub request: &'a mut backend::Request,
+    pub request: &'a mut (backend::Request + 'a),
     pub media: &'a media::Media,
     pub ext: typemap::TypeMap,
     pub response: backend::Response
@@ -24,8 +24,8 @@ pub type ClientResult<'a> = backend::HandleResult<Client<'a>>;
 
 impl<'a> Client<'a> {
 
-    pub fn new(app: &'a app::Application, endpoint: &'a endpoint::Endpoint, 
-               request: &'a mut backend::Request, media: &'a media::Media) -> Client<'a> {
+    pub fn new<'r>(app: &'a app::Application, endpoint: &'a endpoint::Endpoint, 
+               request: &'a mut (backend::Request + 'r), media: &'a media::Media) -> Client<'a> {
         Client {
             app: app,
             endpoint: endpoint,
@@ -85,7 +85,7 @@ impl<'a> Client<'a> {
     }
 
     pub fn error<T: Error>(self, error: T) -> ClientResult<'a> {
-        Err(Box::new(error) as Box<Error>)
+        Err(error_response!(error))
     }
 
     pub fn json(mut self, result: &json::Json) -> ClientResult<'a> {
@@ -105,14 +105,14 @@ impl<'a> Client<'a> {
         let absolute_path = match os::make_absolute(path) {
             Ok(path) => path,
             Err(err) => {
-                return Err(Box::new(errors::File(err)) as Box<Error>);
+                return Err(error_response!(errors::File(err)));
             }
         };
 
         match self.response.push_file(&absolute_path) {
             Ok(()) => Ok(self),
             Err(err) => {
-                return Err(Box::new(errors::File(err)) as Box<Error>);
+                return Err(error_response!(errors::File(err)));
             }
         } 
     }
diff --git a/src/framework/endpoint.rs b/src/framework/endpoint.rs
index ab3052fa..723a35bc 100644
--- a/src/framework/endpoint.rs
+++ b/src/framework/endpoint.rs
@@ -92,15 +92,17 @@ impl Endpoint {
             let coercer = self.coercer.as_ref().unwrap();
             match coercer.process(params) {
                 Ok(()) => Ok(()),
-                Err(err) => return Err(Box::new(errors::Validation{ reason: err }) as Box<errors::Error>)
+                Err(err) => return Err(error_response!(errors::Validation{ reason: err }))
             }   
         } else {
             Ok(())
         }
     }
 
-    pub fn call_decode(&self, params: &mut json::Object, req: &mut backend::Request, 
-                       info: &mut framework::CallInfo) -> backend::HandleResult<backend::Response> {
+    pub fn call_endpoint<'a>(&self, 
+        params: &mut json::Object, 
+        req: &'a mut (backend::Request + 'a), 
+        info: &mut framework::CallInfo) -> backend::HandleResult<backend::Response> {
         
         let mut client = framework::Client::new(info.app, self, req, &info.media);
 
@@ -128,8 +130,11 @@ impl Endpoint {
         Ok(client.move_response())
     }
 
-    fn call_callbacks(cbs: &Vec<framework::Callback>, client: &mut framework::Client, params: &mut json::Object) 
-    -> backend::HandleSuccessResult {
+    fn call_callbacks(
+        cbs: &Vec<framework::Callback>, 
+        client: &mut framework::Client, 
+        params: &mut json::Object) -> backend::HandleSuccessResult {
+
         for cb in cbs.iter() {
             try!(cb(client, params));
         }
@@ -140,20 +145,23 @@ impl Endpoint {
 }
 
 impl framework::ApiHandler for Endpoint {
-    fn api_call(&self, rest_path: &str, params: &mut json::Object, req: &mut backend::Request, 
-                info: &mut framework::CallInfo) -> backend::HandleResult<backend::Response> {
+    fn api_call<'r>(&self, 
+        rest_path: &str, 
+        params: &mut json::Object, 
+        req: &'r mut (backend::Request + 'r), 
+        info: &mut framework::CallInfo) -> backend::HandleResult<backend::Response> {
 
         // method::Method guard
         if req.method() != &self.method {
-            return Err(Box::new(errors::NotMatch) as Box<errors::Error>)
+            return Err(error_response!(errors::NotMatch))
         }
 
         match self.path.is_match(rest_path) {
             Some(captures) =>  {
                 self.path.apply_captures(params, captures);
-                self.call_decode(params, req, info)
+                self.call_endpoint(params, req, info)
             },
-            None => Err(Box::new(errors::NotMatch) as Box<errors::Error>)
+            None => Err(error_response!(errors::NotMatch))
         }
 
     }
diff --git a/src/framework/formatters.rs b/src/framework/formatters.rs
deleted file mode 100644
index 44de8e1c..00000000
--- a/src/framework/formatters.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-
-use serialize::json::{ToJson, as_pretty_json};
-
-use errors::{self, Error};
-use framework;
-use framework::media;
-use backend;
-use server::status;
-
-
-pub fn create_default_error_formatter() -> framework::ErrorFormatter  {
-    let closure = |&: err: &Box<errors::Error>, media: &media::Media| -> Option<backend::Response> {
-        match err.downcast::<errors::Validation>() {
-            Some(err) => {
-                match media.format {
-                    media::Format::JsonFormat => Some(backend::Response::from_json(
-                        status::StatusCode::BadRequest, 
-                        &err.reason.to_json()
-                    )),
-                    // TODO: Make formatter for a mere mortals
-                    _ => Some(
-                        backend::Response::from_string(
-                            status::StatusCode::BadRequest, 
-                            as_pretty_json(&err.reason.to_json()).indent(4u32).to_string()
-                        )
-                    )  
-                }
-            },
-            None => None
-        }
-    };
-
-    Box::new(closure)
-}
-
diff --git a/src/framework/mod.rs b/src/framework/mod.rs
index 7963e69c..6dc97bd5 100644
--- a/src/framework/mod.rs
+++ b/src/framework/mod.rs
@@ -20,7 +20,6 @@ pub mod namespace;
 pub mod client;
 pub mod media;
 pub mod path;
-pub mod formatters;
 pub mod app;
 
 pub struct CallInfo<'a> {
@@ -30,7 +29,7 @@ pub struct CallInfo<'a> {
 }
 
 pub trait ApiHandler: ::std::any::Any {
-    fn api_call<'a>(&'a self, &str, &mut json::Object, &mut backend::Request, &mut CallInfo<'a>) -> backend::HandleResult<backend::Response>;
+    fn api_call<'a, 'b>(&'a self, &str, &mut json::Object, &'b mut (backend::Request + 'b), &mut CallInfo<'a>) -> backend::HandleResult<backend::Response>;
 }
 
 mopafy!(ApiHandler);
diff --git a/src/framework/namespace.rs b/src/framework/namespace.rs
index 88c4974a..776c6480 100644
--- a/src/framework/namespace.rs
+++ b/src/framework/namespace.rs
@@ -50,10 +50,11 @@ impl Namespace {
         if self.coercer.is_some() {
             // validate and coerce params
             let coercer = self.coercer.as_ref().unwrap();
-            match coercer.process(params) {
-                Ok(()) => Ok(()),
-                Err(err) => return Err(Box::new(errors::Validation{ reason: err }) as Box<errors::Error>)
-            }   
+            let val_result = coercer.process(params);
+
+            val_result.map_err(|err| {
+                error_response!(errors::Validation{ reason: err })
+            })
         } else {
             Ok(())
         }
@@ -61,16 +62,16 @@ impl Namespace {
 }
 
 impl framework::ApiHandler for Namespace {
-    fn api_call<'a>(&'a self, rest_path: &str, params: &mut json::Object, req: &mut backend::Request, 
+    fn api_call<'a, 'r>(&'a self, rest_path: &str, params: &mut json::Object, req: &'r mut (backend::Request + 'r), 
                     info: &mut framework::CallInfo<'a>) -> backend::HandleResult<backend::Response> {
 
         let rest_path: &str = match self.path.is_match(rest_path) {
             Some(captures) =>  {
                 let captured_length = captures.at(0).map_or(0, |c| c.len());
                 self.path.apply_captures(params, captures);
-                path::normalize(rest_path.slice_from(captured_length))
+                path::normalize(&rest_path[(captured_length)..])
             },
-            None => return Err(Box::new(errors::NotMatch) as Box<errors::Error>)
+            None => return Err(error_response!(errors::NotMatch))
         };
 
         try!(self.validate(params));
diff --git a/src/framework/nesting.rs b/src/framework/nesting.rs
index 553f8302..532c0d92 100644
--- a/src/framework/nesting.rs
+++ b/src/framework/nesting.rs
@@ -128,21 +128,21 @@ pub trait Nesting: Node {
         self.get_after_validation_mut().push(Box::new(callback)); 
     }
 
-    fn call_handlers<'a>(&'a self, rest_path: &str, params: &mut json::Object, req: &mut backend::Request, 
+    fn call_handlers<'a, 'r>(&'a self, rest_path: &str, params: &mut json::Object, req: &'r mut (backend::Request + 'r), 
                          info: &mut framework::CallInfo<'a>) -> backend::HandleResult<backend::Response> {
+        
         for handler in self.get_handlers().iter() {
             match handler.api_call(rest_path, params, req, info) {
                 Ok(response) => return Ok(response),
-                Err(err) => {
-                    match err.downcast::<errors::NotMatch>() {
-                        Some(_) => (),
-                        None => return Err(err),
+                Err(error_response) => {
+                    if !error_response.error.is::<errors::NotMatch>() {
+                        return Err(error_response)
                     }
                 }
             };
         }
 
-        Err(Box::new(errors::NotMatch) as Box<errors::Error>)
+        Err(error_response!(errors::NotMatch))
     }
 
 }
\ No newline at end of file
diff --git a/src/framework/path.rs b/src/framework/path.rs
index bf0c0277..32ad8c42 100644
--- a/src/framework/path.rs
+++ b/src/framework/path.rs
@@ -12,7 +12,7 @@ pub struct Path {
 
 pub fn normalize<'a>(path: &'a str) -> &'a str {
     if path.starts_with("/") {
-        path.slice_from(1)
+        &path[1..]
     } else {
         path
     }
diff --git a/src/lib.rs b/src/lib.rs
index 514bb470..bc5ebf61 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,12 @@
 #![crate_name = "rustless"]
 #![crate_type = "rlib"]
 #![feature(plugin)]
-#![allow(unstable)]
-#![deny(warnings)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(std_misc)]
+#![feature(os)]
+// #![deny(warnings)]
 #![deny(bad_style)]
 
 #[plugin]
@@ -26,8 +30,8 @@ extern crate jsonway;
 #[macro_use] #[no_link]
 extern crate mopa;
 
-pub use backend::{Request, SimpleRequest, Response};
-pub use backend::{Handler, HandleResult, HandleSuccessResult};
+pub use backend::{Request, SimpleRequest, Response, Handler, HandleResult, HandleSuccessResult};
+pub use errors::{ErrorResponse};
 pub use framework::{
     Endpoint, Client, Api, Application, Namespace, Nesting, Media, Versioning
 };
@@ -46,8 +50,8 @@ macro_rules! impl_extensible {
     )
 }
 
-pub mod errors;
+#[macro_use] pub mod errors;
+#[macro_use] pub mod backend;
 pub mod server;
-pub mod backend;
 pub mod framework;
 pub mod batteries;
\ No newline at end of file


Test patch:
diff --git a/tests/callbacks.rs b/tests/callbacks.rs
index bd4b6f75..ee649a51 100644
--- a/tests/callbacks.rs
+++ b/tests/callbacks.rs
@@ -1,18 +1,26 @@
-use std;
+use std::error;
+use std::error::Error as StdError;
+use std::fmt;
 use valico;
 use rustless::{self, Nesting};
 use rustless::server::status;
-use rustless::errors::{self, Error};
+use rustless::errors::{Error};
 
 #[derive(Show)]
 pub struct UnauthorizedError;
 
-impl std::error::Error for UnauthorizedError {
+impl error::Error for UnauthorizedError {
     fn description(&self) -> &'static str {
         return "Unauthorized";
     }
 }
 
+impl fmt::Display for UnauthorizedError {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        self.description().fmt(formatter)
+    }
+}
+
 #[test]
 fn it_invokes_callbacks() {
 
@@ -20,11 +28,10 @@ fn it_invokes_callbacks() {
         api.prefix("api");
 
         api.error_formatter(|err, _media| {
-            match err.downcast::<UnauthorizedError>() {
-                Some(_) => {
-                    return Some(rustless::Response::from_string(status::StatusCode::Unauthorized, "Please provide correct `token` parameter".to_string()))
-                },
-                None => None
+            if err.is::<UnauthorizedError>() {
+                Some(rustless::Response::from_string(status::StatusCode::Unauthorized, "Please provide correct `token` parameter".to_string()))
+            } else {
+                None
             }
         });
 
@@ -37,13 +44,16 @@ fn it_invokes_callbacks() {
             // Using after_validation callback to check token
             admin_ns.after_validation(|_client, params| {
                 match params.get(&"token".to_string()) {
-                    // We can unwrap() safely because token in validated already
+                    // We can.unwrap() safely because token in validated already
                     Some(token) => if token.as_string().unwrap().as_slice() == "password1" { return Ok(()) },
                     None => ()
                 }
 
                 // Fire error from callback is token is wrong
-                return Err(Box::new(UnauthorizedError) as Box<errors::Error>)
+                return Err(rustless::ErrorResponse{
+                    error: Box::new(UnauthorizedError) as Box<Error>,
+                    response: None
+                })
             });
 
             // This `/api/admin/server_status` endpoint is secure now
@@ -56,13 +66,13 @@ fn it_invokes_callbacks() {
         })
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status?token=wrong%20token").unwrap();
-    assert_eq!(response.status, status::StatusCode::Unauthorized);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status?token=wrong%20token").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::Unauthorized);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status?token=password1").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/admin/server_status?token=password1").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
 }
diff --git a/tests/namespace.rs b/tests/namespace.rs
index bafe3286..1d47ba7f 100644
--- a/tests/namespace.rs
+++ b/tests/namespace.rs
@@ -15,19 +15,19 @@ fn it_allows_to_create_namespace() {
 
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns2/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns2/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns3/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns3/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns4/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns4/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns5/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns5/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
 }
@@ -50,7 +50,7 @@ fn it_allows_nested_namespaces() {
 
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1/ns2/ns3/ns4/ns5/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1/ns2/ns3/ns4/ns5/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
 }
@@ -76,13 +76,13 @@ fn it_allows_grouping_with_zero_path() {
 
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/ns1").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/ns1").unwrap();
+    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/ns1").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Delete, "http://127.0.0.1:3000/api/ns1").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Delete, "http://127.0.0.1:3000/api/ns1").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
 }
\ No newline at end of file
diff --git a/tests/params.rs b/tests/params.rs
index 783eee84..d7947161 100644
--- a/tests/params.rs
+++ b/tests/params.rs
@@ -14,16 +14,16 @@ fn it_validates_endpoint_simple_path_params() {
         })
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/Skywalker/messages/100").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/Skywalker/messages/100").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/12").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/12").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
 }
@@ -44,13 +44,13 @@ fn it_validates_typed_endpoint_path_params() {
         })
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/Skywalker/messages/100").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);    
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/Skywalker/messages/100").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);    
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/Skywalker").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/Skywalker").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/12").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/messages/12").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
 }
@@ -73,19 +73,19 @@ fn it_validates_query_params() {
         })
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);    
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);    
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=1").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);    
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=1").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);    
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=fulll").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);        
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=fulll").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);        
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=full").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=full").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);    
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=simple").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100?profile=simple").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);   
      
 }
@@ -115,14 +115,14 @@ fn it_validates_common_namespace_params() {
         })
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100").unwrap();
-    assert_eq!(response.status, status::StatusCode::BadRequest);    
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);    
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/profile/full").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/profile/full").err().unwrap();
     // missed `ext` param
-    assert_eq!(response.status, status::StatusCode::BadRequest);  
+    assert_eq!(err_resp.response.status, status::StatusCode::BadRequest);  
 
-    let mut response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/profile/full?ext=some").unwrap();
+    let mut response = call_app!(app, Get, "http://127.0.0.1:3000/api/users/100/profile/full?ext=some").ok().unwrap();
         println!("{}", resp_body!(response));
     assert_eq!(response.status, status::StatusCode::Ok);   
 }
\ No newline at end of file
diff --git a/tests/prefix.rs b/tests/prefix.rs
index e9bfd704..570fb3d5 100644
--- a/tests/prefix.rs
+++ b/tests/prefix.rs
@@ -9,11 +9,11 @@ fn it_allows_prefix() {
         edp_stub!(api);
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
     // not found because prefix is not present
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -28,13 +28,13 @@ fn it_allows_nested_prefix() {
         }))
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/info").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/info").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/nested_api/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/nested_api/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -50,12 +50,12 @@ fn it_allows_prefix_with_path_versioning() {
         }))
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/info").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/info").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/api/v1/info").unwrap();
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/api/v1/info").err().unwrap();
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 }
\ No newline at end of file
diff --git a/tests/redirect.rs b/tests/redirect.rs
index 8ef643f0..0dff951f 100644
--- a/tests/redirect.rs
+++ b/tests/redirect.rs
@@ -14,7 +14,7 @@ fn it_allows_redirect() {
         });
     });
 
-    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/redirect_me/google.com").unwrap();
+    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/redirect_me/google.com").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Found);
     let &header::Location(ref location) = response.headers.get::<header::Location>().unwrap();
     assert_eq!(location.as_slice(), "google.com")
@@ -33,7 +33,7 @@ fn it_allows_permanent_redirect() {
         });
     });
 
-    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/redirect_me/google.com").unwrap();
+    let response = call_app!(app, Post, "http://127.0.0.1:3000/api/redirect_me/google.com").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::MovedPermanently);
     let &header::Location(ref location) = response.headers.get::<header::Location>().unwrap();
     assert_eq!(location.as_slice(), "google.com")
diff --git a/tests/serializers.rs b/tests/serializers.rs
index fbd4d845..638b38a0 100644
--- a/tests/serializers.rs
+++ b/tests/serializers.rs
@@ -16,7 +16,7 @@ fn it_serializes_json_properly() {
 
         api.get("status", |endpoint| {
             endpoint.handle(|client, params| {
-                client.json(&jsonway::JsonWay::object(|json| {
+                client.json(&jsonway::object(|json| {
                     json.set("uptime", "Ok".to_string());
                     json.set("echo_params", json::Json::Object(params.clone()));
                 }).unwrap())
@@ -24,7 +24,7 @@ fn it_serializes_json_properly() {
         })
     });
 
-    let mut response = call_app!(app, Get, "http://127.0.0.1:3000/api/status").unwrap();
+    let mut response = call_app!(app, Get, "http://127.0.0.1:3000/api/status").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
     {
diff --git a/tests/tests.rs b/tests/tests.rs
index 8e93007a..4197ed21 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1,6 +1,8 @@
-#![deny(warnings)]
+// #![deny(warnings)]
 #![deny(bad_style)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
 
 #[macro_use]
 extern crate rustless;
@@ -23,10 +25,10 @@ macro_rules! sr {
 #[macro_export]
 macro_rules! call_app {
     ($app:ident, $method:ident, $url:expr) => {
-        $app.call_with_not_found(&mut sr!($method, $url))
+        $app.call(&mut sr!($method, $url))
     };    
     ($app:ident, $method:ident, $url:expr, $blk:expr) => {
-        $app.call_with_not_found(&mut sr!($method, $url, $blk))
+        $app.call(&mut sr!($method, $url, $blk))
     };
 }
 
diff --git a/tests/versioning.rs b/tests/versioning.rs
index 06aeabfa..40c66d69 100644
--- a/tests/versioning.rs
+++ b/tests/versioning.rs
@@ -10,15 +10,15 @@ fn it_pass_accept_header_versioning() {
         edp_stub!(api);
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
     // not found because accept-header is not present
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
     let response = call_app!(app, Get, "http://127.0.0.1:3000/info", |&: rq| {
         rq.headers_mut().set(
             header::Accept( vec![mime!("application/vnd.infoapi.v1+json")] )
         );
-    }).unwrap();
+    }).ok().unwrap();
 
     assert_eq!(response.status, status::StatusCode::Ok);
 }
@@ -30,11 +30,11 @@ fn it_pass_path_versioning() {
         edp_stub!(api);
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
     // not found because version is not present in path
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -45,11 +45,11 @@ fn it_pass_param_versioning() {
         edp_stub!(api);
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/info").err().unwrap();
     // not found because version is not present in param
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info?v=v1").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/info?v=v1").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -70,14 +70,14 @@ fn it_pass_nesting_param_versioning() {
         }))
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info?v=v1").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/info?v=v1").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/nested_info?v=v1").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/nested_info?v=v1").err().unwrap();
     // not found because nested_info param in not present
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/nested_info?v=v1&nested_ver=v2").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/nested_info?v=v1&nested_ver=v2").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -98,14 +98,14 @@ fn it_pass_nesting_path_versioning() {
         }))
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/nested_info").unwrap();
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/v1/nested_info").err().unwrap();
     // not found because v2 in not present in path
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/v2/nested_info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/v1/v2/nested_info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
 
@@ -129,17 +129,17 @@ fn it_pass_nesting_crazy_mixed_versioning_never_do_this() {
         rq.headers_mut().set(
             header::Accept( vec![mime!("application/vnd.infoapi.v1+json")] )
         );
-    }).unwrap();
+    }).ok().unwrap();
 
     assert_eq!(response.status, status::StatusCode::Ok);
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/v2/nested_nested_info", |&: rq| {
+    let err_resp = call_app!(app, Get, "http://127.0.0.1:3000/v2/nested_nested_info", |&: rq| {
         rq.headers_mut().set(
             header::Accept( vec![mime!("application/vnd.infoapi.v1+json")] )
         );
-    }).unwrap();
+    }).err().unwrap();
 
-    assert_eq!(response.status, status::StatusCode::NotFound);
+    assert_eq!(err_resp.response.status, status::StatusCode::NotFound);
 }
 
 #[test]
@@ -148,6 +148,6 @@ fn it_pass_without_versioning() {
         edp_stub!(api);
     });
 
-    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").unwrap();
+    let response = call_app!(app, Get, "http://127.0.0.1:3000/info").ok().unwrap();
     assert_eq!(response.status, status::StatusCode::Ok);
 }
\ No newline at end of file