Rename '#[error]' to '#[catch]', 'errors!' to 'catchers!'.

This commit is contained in:
Sergio Benitez 2017-09-22 19:04:14 -07:00
parent 92ce006e2c
commit 237c673be4
21 changed files with 98 additions and 83 deletions

View File

@ -1,5 +1,5 @@
use ::{CATCH_STRUCT_PREFIX, CATCH_FN_PREFIX, CATCHER_ATTR}; use ::{CATCH_STRUCT_PREFIX, CATCH_FN_PREFIX, CATCHER_ATTR};
use parser::ErrorParams; use parser::CatchParams;
use utils::*; use utils::*;
use syntax::codemap::{Span}; use syntax::codemap::{Span};
@ -11,21 +11,21 @@ use syntax::parse::token;
const ERR_PARAM: &'static str = "__err"; const ERR_PARAM: &'static str = "__err";
const REQ_PARAM: &'static str = "__req"; const REQ_PARAM: &'static str = "__req";
trait ErrorGenerateExt { trait CatchGenerateExt {
fn generate_fn_arguments(&self, &ExtCtxt, Ident, Ident) -> Vec<TokenTree>; fn generate_fn_arguments(&self, &ExtCtxt, Ident, Ident) -> Vec<TokenTree>;
} }
impl ErrorGenerateExt for ErrorParams { impl CatchGenerateExt for CatchParams {
fn generate_fn_arguments(&self, ecx: &ExtCtxt, err: Ident, req: Ident) fn generate_fn_arguments(&self, ecx: &ExtCtxt, err: Ident, req: Ident)
-> Vec<TokenTree> { -> Vec<TokenTree> {
let arg_help = "error handlers can take either a `rocket::Error` or \ let arg_help = "error catchers can take either a `rocket::Error`, \
`rocket::Request` type, or both."; `rocket::Request` type, or both.";
// Retrieve the params from the user's handler and check the number. // Retrieve the params from the user's handler and check the number.
let input_args = &self.annotated_fn.decl().inputs; let input_args = &self.annotated_fn.decl().inputs;
if input_args.len() > 2 { if input_args.len() > 2 {
let sp = self.annotated_fn.span(); let sp = self.annotated_fn.span();
ecx.struct_span_err(sp, "error handlers can have at most 2 arguments") ecx.struct_span_err(sp, "error catchers can have at most 2 arguments")
.help(arg_help).emit() .help(arg_help).emit()
} }
@ -35,8 +35,10 @@ impl ErrorGenerateExt for ErrorParams {
TyKind::Rptr(..) => Some(req), TyKind::Rptr(..) => Some(req),
TyKind::Path(..) => Some(err), TyKind::Path(..) => Some(err),
_ => { _ => {
ecx.struct_span_err(ty.span, "unexpected error handler argument") ecx.struct_span_err(ty.span, "unknown error catcher argument")
.help(arg_help).emit(); .help(arg_help)
.emit();
None None
} }
} }
@ -46,24 +48,24 @@ impl ErrorGenerateExt for ErrorParams {
} }
} }
pub fn error_decorator(ecx: &mut ExtCtxt, pub fn catch_decorator(
ecx: &mut ExtCtxt,
sp: Span, sp: Span,
meta_item: &MetaItem, meta_item: &MetaItem,
annotated: Annotatable) annotated: Annotatable
-> Vec<Annotatable> ) -> Vec<Annotatable> {
{
let mut output = Vec::new(); let mut output = Vec::new();
// Parse the parameters from the error annotation. // Parse the parameters from the `catch` annotation.
let error = ErrorParams::from(ecx, sp, meta_item, &annotated); let catch = CatchParams::from(ecx, sp, meta_item, &annotated);
// Get all of the information we learned from the attribute + function. // Get all of the information we learned from the attribute + function.
let user_fn_name = error.annotated_fn.ident(); let user_fn_name = catch.annotated_fn.ident();
let catch_fn_name = user_fn_name.prepend(CATCH_FN_PREFIX); let catch_fn_name = user_fn_name.prepend(CATCH_FN_PREFIX);
let code = error.code.node; let code = catch.code.node;
let err_ident = Ident::from_str(ERR_PARAM); let err_ident = Ident::from_str(ERR_PARAM);
let req_ident = Ident::from_str(REQ_PARAM); let req_ident = Ident::from_str(REQ_PARAM);
let fn_arguments = error.generate_fn_arguments(ecx, err_ident, req_ident); let fn_arguments = catch.generate_fn_arguments(ecx, err_ident, req_ident);
// Push the Rocket generated catch function. // Push the Rocket generated catch function.
emit_item(&mut output, quote_item!(ecx, emit_item(&mut output, quote_item!(ecx,
@ -78,7 +80,7 @@ pub fn error_decorator(ecx: &mut ExtCtxt,
} }
).expect("catch function")); ).expect("catch function"));
// Push the static catch info. This is what the errors! macro refers to. // Push the static catch info. This is what the `catchers!` macro refers to.
let struct_name = user_fn_name.prepend(CATCH_STRUCT_PREFIX); let struct_name = user_fn_name.prepend(CATCH_STRUCT_PREFIX);
emit_item(&mut output, quote_item!(ecx, emit_item(&mut output, quote_item!(ecx,
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]

View File

@ -1,8 +1,8 @@
mod route; mod route;
mod error; mod catch;
mod derive_form; mod derive_form;
pub use self::route::*; pub use self::route::*;
pub use self::error::*; pub use self::catch::*;
pub use self::derive_form::*; pub use self::derive_form::*;

View File

@ -17,7 +17,7 @@
//! * **head** //! * **head**
//! * **patch** //! * **patch**
//! * **options** //! * **options**
//! * **error** //! * **catch**
//! //!
//! The grammar for all _route_ attributes, including **route**, **get**, //! The grammar for all _route_ attributes, including **route**, **get**,
//! **put**, **post**, **delete**, **head**, **patch**, and **options** is //! **put**, **post**, **delete**, **head**, **patch**, and **options** is
@ -53,15 +53,15 @@
//! //!
//! #[get("/hello")] //! #[get("/hello")]
//! //!
//! The syntax for the **error** attribute is: //! The syntax for the **catch** attribute is:
//! //!
//! <pre> //! <pre>
//! error := INTEGER //! catch := INTEGER
//! </pre> //! </pre>
//! //!
//! A use of the `error` attribute looks like: //! A use of the `catch` attribute looks like:
//! //!
//! #[error(404)] //! #[catch(404)]
//! //!
//! ## Custom Derives //! ## Custom Derives
//! //!
@ -115,10 +115,10 @@
//! This crate implements the following procedural macros: //! This crate implements the following procedural macros:
//! //!
//! * **routes** //! * **routes**
//! * **errors** //! * **catchers**
//! * **uri** //! * **uri**
//! //!
//! The syntax for `routes!` and `errors!` is defined as: //! The syntax for `routes!` and `catchers!` is defined as:
//! //!
//! <pre> //! <pre>
//! macro := PATH (',' PATH)* //! macro := PATH (',' PATH)*
@ -283,7 +283,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
register_macros!(reg, register_macros!(reg,
"routes" => routes, "routes" => routes,
"errors" => errors, "catchers" => catchers,
"uri" => uri, "uri" => uri,
"rocket_internal_uri" => uri_internal "rocket_internal_uri" => uri_internal
); );
@ -293,7 +293,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
); );
register_decorators!(reg, register_decorators!(reg,
"error" => error_decorator, "catch" => catch_decorator,
"route" => route_decorator, "route" => route_decorator,
"get" => get_decorator, "get" => get_decorator,
"put" => put_decorator, "put" => put_decorator,

View File

@ -64,7 +64,7 @@ pub fn routes(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
} }
#[rustfmt_skip] #[rustfmt_skip]
pub fn errors(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) pub fn catchers(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-> Box<MacResult + 'static> { -> Box<MacResult + 'static> {
prefixing_vec_macro(CATCH_STRUCT_PREFIX, |ecx, path| { prefixing_vec_macro(CATCH_STRUCT_PREFIX, |ecx, path| {
quote_expr!(ecx, rocket::Catcher::from(&$path)) quote_expr!(ecx, rocket::Catcher::from(&$path))

View File

@ -7,13 +7,13 @@ use rocket::http::Status;
use utils::{span, MetaItemExt}; use utils::{span, MetaItemExt};
use super::Function; use super::Function;
/// This structure represents the parsed `error` attribute. /// This structure represents the parsed `catch` attribute.
pub struct ErrorParams { pub struct CatchParams {
pub annotated_fn: Function, pub annotated_fn: Function,
pub code: Spanned<u16>, pub code: Spanned<u16>,
} }
impl ErrorParams { impl CatchParams {
/// Parses the route attribute from the given decorator context. If the /// Parses the route attribute from the given decorator context. If the
/// parse is not successful, this function exits early with the appropriate /// parse is not successful, this function exits early with the appropriate
/// error message to the user. /// error message to the user.
@ -21,7 +21,7 @@ impl ErrorParams {
sp: Span, sp: Span,
meta_item: &MetaItem, meta_item: &MetaItem,
annotated: &Annotatable) annotated: &Annotatable)
-> ErrorParams { -> CatchParams {
let function = Function::from(annotated).unwrap_or_else(|item_sp| { let function = Function::from(annotated).unwrap_or_else(|item_sp| {
ecx.span_err(sp, "this attribute can only be used on functions..."); ecx.span_err(sp, "this attribute can only be used on functions...");
ecx.span_fatal(item_sp, "...but was applied to the item above."); ecx.span_fatal(item_sp, "...but was applied to the item above.");
@ -40,7 +40,7 @@ impl ErrorParams {
ecx.span_fatal(sp, "attribute can only have one `code` parameter"); ecx.span_fatal(sp, "attribute can only have one `code` parameter");
} }
ErrorParams { CatchParams {
annotated_fn: function, annotated_fn: function,
code: parse_code(ecx, &meta_items[0]) code: parse_code(ecx, &meta_items[0])
} }
@ -74,8 +74,8 @@ fn parse_code(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> Spanned<u16> {
} else { } else {
ecx.struct_span_err(sp, r#"expected `code = int` or an integer literal"#) ecx.struct_span_err(sp, r#"expected `code = int` or an integer literal"#)
.help(r#"you can specify the code directly as an integer, .help(r#"you can specify the code directly as an integer,
e.g: #[error(404)], or as a key-value pair, e.g: #[catch(404)], or as a key-value pair,
e.g: $[error(code = 404)]"#) e.g: $[catch(code = 404)]"#)
.emit(); .emit();
} }

View File

@ -1,6 +1,6 @@
mod keyvalue; mod keyvalue;
mod route; mod route;
mod error; mod catch;
mod param; mod param;
mod function; mod function;
mod uri; mod uri;
@ -8,7 +8,7 @@ mod uri_macro;
pub use self::keyvalue::KVSpanned; pub use self::keyvalue::KVSpanned;
pub use self::route::RouteParams; pub use self::route::RouteParams;
pub use self::error::ErrorParams; pub use self::catch::CatchParams;
pub use self::param::Param; pub use self::param::Param;
pub use self::function::Function; pub use self::function::Function;
pub use self::uri_macro::{Args, InternalUriParams, UriParams, Validation}; pub use self::uri_macro::{Args, InternalUriParams, UriParams, Validation};

View File

@ -5,19 +5,19 @@ extern crate rocket;
use rocket::{Error, Request}; use rocket::{Error, Request};
#[error(404)] #[catch(404)]
fn err0() -> &'static str { "hi" } fn err0() -> &'static str { "hi" }
#[error(404)] #[catch(404)]
fn err1a(_err: Error) -> &'static str { "hi" } fn err1a(_err: Error) -> &'static str { "hi" }
#[error(404)] #[catch(404)]
fn err1b(_req: &Request) -> &'static str { "hi" } fn err1b(_req: &Request) -> &'static str { "hi" }
#[error(404)] #[catch(404)]
fn err2a(_err: Error, _req: &Request) -> &'static str { "hi" } fn err2a(_err: Error, _req: &Request) -> &'static str { "hi" }
#[error(404)] #[catch(404)]
fn err2b<'a>(_err: Error, _req: &'a Request) -> &'a str { "hi" } fn err2b<'a>(_err: Error, _req: &'a Request) -> &'a str { "hi" }
#[test] #[test]

View File

@ -5,14 +5,8 @@ extern crate rocket;
use rocket::{Error, Request}; use rocket::{Error, Request};
#[error(404)] #[catch(404)]
fn err_a(_a: Error, _b: Request, _c: Error) -> &'static str { "hi" } fn err_a(_a: Error, _b: Request, _c: Error) -> &'static str { "hi" }
//~^ ERROR: can have at most 2
#[error(404)] #[catch(404)]
fn err_b(_a: (isize, usize)) -> &'static str { "hi" } fn err_b(_a: (isize, usize)) -> &'static str { "hi" }
//~^ ERROR: unexpected error handler argument
fn main() {
}

View File

@ -0,0 +1,18 @@
error: error catchers can have at most 2 arguments
--> $DIR/bad-error-fn.rs:9:1
|
9 | fn err_a(_a: Error, _b: Request, _c: Error) -> &'static str { "hi" }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: error catchers can take either a `rocket::Error`, `rocket::Request` type, or both.
error: unknown error catcher argument
--> $DIR/bad-error-fn.rs:12:14
|
12 | fn err_b(_a: (isize, usize)) -> &'static str { "hi" }
| ^^^^^^^^^^^^^^
|
= help: error catchers can take either a `rocket::Error`, `rocket::Request` type, or both.
error: aborting due to 2 previous errors

View File

@ -35,7 +35,7 @@ fn post_hello(age: u8, name: String) -> content::Json<String> {
content::Json(serde_json::to_string(&person).unwrap()) content::Json(serde_json::to_string(&person).unwrap())
} }
#[error(404)] #[catch(404)]
fn not_found(request: &Request) -> content::Html<String> { fn not_found(request: &Request) -> content::Html<String> {
let html = match request.format() { let html = match request.format() {
Some(ref mt) if !mt.is_json() && !mt.is_plain() => { Some(ref mt) if !mt.is_json() && !mt.is_plain() => {
@ -52,6 +52,6 @@ fn not_found(request: &Request) -> content::Html<String> {
fn main() { fn main() {
rocket::ignite() rocket::ignite()
.mount("/hello", routes![get_hello, post_hello]) .mount("/hello", routes![get_hello, post_hello])
.catch(errors![not_found]) .catch(catchers![not_found])
.launch(); .launch();
} }

View File

@ -9,7 +9,7 @@ fn test<H>(method: Method, uri: &str, header: H, status: Status, body: String)
{ {
let rocket = rocket::ignite() let rocket = rocket::ignite()
.mount("/hello", routes![super::get_hello, super::post_hello]) .mount("/hello", routes![super::get_hello, super::post_hello])
.catch(errors![super::not_found]); .catch(catchers![super::not_found]);
let client = Client::new(rocket).unwrap(); let client = Client::new(rocket).unwrap();
let mut response = client.req(method, uri).header(header).dispatch(); let mut response = client.req(method, uri).header(header).dispatch();

View File

@ -12,7 +12,7 @@ fn hello(name: String, age: i8) -> String {
format!("Hello, {} year old named {}!", age, name) format!("Hello, {} year old named {}!", age, name)
} }
#[error(404)] #[catch(404)]
fn not_found(req: &rocket::Request) -> content::Html<String> { fn not_found(req: &rocket::Request) -> content::Html<String> {
content::Html(format!("<p>Sorry, but '{}' is not a valid path!</p> content::Html(format!("<p>Sorry, but '{}' is not a valid path!</p>
<p>Try visiting /hello/&lt;name&gt;/&lt;age&gt; instead.</p>", <p>Try visiting /hello/&lt;name&gt;/&lt;age&gt; instead.</p>",
@ -23,7 +23,7 @@ fn main() {
let e = rocket::ignite() let e = rocket::ignite()
// .mount("/", routes![hello, hello]) // uncoment this to get an error // .mount("/", routes![hello, hello]) // uncoment this to get an error
.mount("/", routes![hello]) .mount("/", routes![hello])
.catch(errors![not_found]) .catch(catchers![not_found])
.launch(); .launch();
println!("Whoops! Rocket didn't launch!"); println!("Whoops! Rocket didn't launch!");

View File

@ -5,7 +5,7 @@ use rocket::http::Status;
fn test(uri: &str, status: Status, body: String) { fn test(uri: &str, status: Status, body: String) {
let rocket = rocket::ignite() let rocket = rocket::ignite()
.mount("/", routes![super::hello]) .mount("/", routes![super::hello])
.catch(errors![super::not_found]); .catch(catchers![super::not_found]);
let client = Client::new(rocket).unwrap(); let client = Client::new(rocket).unwrap();
let mut response = client.get(uri).dispatch(); let mut response = client.get(uri).dispatch();

View File

@ -32,7 +32,7 @@ fn get(name: String) -> Template {
Template::render("index", &context) Template::render("index", &context)
} }
#[error(404)] #[catch(404)]
fn not_found(req: &Request) -> Template { fn not_found(req: &Request) -> Template {
let mut map = std::collections::HashMap::new(); let mut map = std::collections::HashMap::new();
map.insert("path", req.uri().as_str()); map.insert("path", req.uri().as_str());
@ -43,7 +43,7 @@ fn rocket() -> rocket::Rocket {
rocket::ignite() rocket::ignite()
.mount("/", routes![index, get]) .mount("/", routes![index, get])
.attach(Template::fairing()) .attach(Template::fairing())
.catch(errors![not_found]) .catch(catchers![not_found])
} }
fn main() { fn main() {

View File

@ -61,7 +61,7 @@ fn get(id: ID, map: State<MessageMap>) -> Option<Json<Message>> {
}) })
} }
#[error(404)] #[catch(404)]
fn not_found() -> JsonValue { fn not_found() -> JsonValue {
json!({ json!({
"status": "error", "status": "error",
@ -72,7 +72,7 @@ fn not_found() -> JsonValue {
fn rocket() -> rocket::Rocket { fn rocket() -> rocket::Rocket {
rocket::ignite() rocket::ignite()
.mount("/message", routes![new, update, get]) .mount("/message", routes![new, update, get])
.catch(errors![not_found]) .catch(catchers![not_found])
.manage(Mutex::new(HashMap::<ID, String>::new())) .manage(Mutex::new(HashMap::<ID, String>::new()))
} }

View File

@ -32,7 +32,7 @@ use yansi::Color::*;
/// # Code Generation /// # Code Generation
/// ///
/// Catchers should rarely be used directly. Instead, they are typically /// Catchers should rarely be used directly. Instead, they are typically
/// declared using the `error` decorator, as follows: /// declared using the `catch` decorator, as follows:
/// ///
/// ```rust /// ```rust
/// #![feature(plugin, decl_macro)] /// #![feature(plugin, decl_macro)]
@ -42,24 +42,24 @@ use yansi::Color::*;
/// ///
/// use rocket::Request; /// use rocket::Request;
/// ///
/// #[error(500)] /// #[catch(500)]
/// fn internal_error() -> &'static str { /// fn internal_error() -> &'static str {
/// "Whoops! Looks like we messed up." /// "Whoops! Looks like we messed up."
/// } /// }
/// ///
/// #[error(400)] /// #[catch(400)]
/// fn not_found(req: &Request) -> String { /// fn not_found(req: &Request) -> String {
/// format!("I couldn't find '{}'. Try something else?", req.uri()) /// format!("I couldn't find '{}'. Try something else?", req.uri())
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// # if false { // We don't actually want to launch the server in an example. /// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite().catch(errors![internal_error, not_found]).launch(); /// rocket::ignite().catch(catchers![internal_error, not_found]).launch();
/// # } /// # }
/// } /// }
/// ``` /// ```
/// ///
/// A function decorated with `error` can take in 0, 1, or 2 parameters: /// A function decorated with `catch` can take in 0, 1, or 2 parameters:
/// `Error`, `&Request`, or both, as desired. /// `Error`, `&Request`, or both, as desired.
pub struct Catcher { pub struct Catcher {
/// The HTTP status code to match against. /// The HTTP status code to match against.
@ -150,7 +150,7 @@ macro_rules! error_page_template {
) )
} }
macro_rules! default_errors { macro_rules! default_catchers {
($($code:expr, $name:expr, $description:expr, $fn_name:ident),+) => ( ($($code:expr, $name:expr, $description:expr, $fn_name:ident),+) => (
let mut map = HashMap::new(); let mut map = HashMap::new();
@ -179,7 +179,7 @@ pub mod defaults {
use error::Error; use error::Error;
pub fn get() -> HashMap<u16, Catcher> { pub fn get() -> HashMap<u16, Catcher> {
default_errors! { default_catchers! {
400, "Bad Request", "The request could not be understood by the server due 400, "Bad Request", "The request could not be understood by the server due
to malformed syntax.", handle_400, to malformed syntax.", handle_400,
401, "Unauthorized", "The request requires user authentication.", 401, "Unauthorized", "The request requires user authentication.",

View File

@ -521,19 +521,19 @@ impl Rocket {
/// ///
/// use rocket::Request; /// use rocket::Request;
/// ///
/// #[error(500)] /// #[catch(500)]
/// fn internal_error() -> &'static str { /// fn internal_error() -> &'static str {
/// "Whoops! Looks like we messed up." /// "Whoops! Looks like we messed up."
/// } /// }
/// ///
/// #[error(400)] /// #[catch(400)]
/// fn not_found(req: &Request) -> String { /// fn not_found(req: &Request) -> String {
/// format!("I couldn't find '{}'. Try something else?", req.uri()) /// format!("I couldn't find '{}'. Try something else?", req.uri())
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// # if false { // We don't actually want to launch the server in an example. /// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite().catch(errors![internal_error, not_found]) /// rocket::ignite().catch(catchers![internal_error, not_found])
/// # .launch(); /// # .launch();
/// # } /// # }
/// } /// }

View File

@ -5,7 +5,7 @@ extern crate rocket;
use rocket::response::Redirect; use rocket::response::Redirect;
#[error(404)] #[catch(404)]
fn not_found() -> Redirect { fn not_found() -> Redirect {
Redirect::to("/") Redirect::to("/")
} }
@ -17,7 +17,7 @@ mod tests {
#[test] #[test]
fn error_catcher_redirect() { fn error_catcher_redirect() {
let client = Client::new(rocket::ignite().catch(errors![not_found])).unwrap(); let client = Client::new(rocket::ignite().catch(catchers![not_found])).unwrap();
let response = client.get("/unknown").dispatch(); let response = client.get("/unknown").dispatch();
println!("Response:\n{:?}", response); println!("Response:\n{:?}", response);

View File

@ -737,22 +737,22 @@ Routing may fail for a variety of reasons. These include:
If any of these conditions occur, Rocket returns an error to the client. To do If any of these conditions occur, Rocket returns an error to the client. To do
so, Rocket invokes the _error catcher_ corresponding to the error's status code. so, Rocket invokes the _error catcher_ corresponding to the error's status code.
A catcher is like a route, except it only handles errors. Catchers are declared A catcher is like a route, except it only handles errors. Catchers are declared
via the `error` attribute, which takes a single integer corresponding to the via the `catch` attribute, which takes a single integer corresponding to the
HTTP status code to catch. For instance, to declare a catcher for **404** HTTP status code to catch. For instance, to declare a catcher for **404**
errors, you'd write: errors, you'd write:
```rust ```rust
#[error(404)] #[catch(404)]
fn not_found(req: &Request) -> String { ... } fn not_found(req: &Request) -> String { ... }
``` ```
As with routes, Rocket needs to know about a catcher before it is used to handle As with routes, Rocket needs to know about a catcher before it is used to handle
errors. The process is similar to mounting: call the `catch` method with a list errors. The process is similar to mounting: call the `catch` method with a list
of catchers via the `errors!` macro. The invocation to add the **404** catcher of catchers via the `catchers!` macro. The invocation to add the **404** catcher
declared above looks like: declared above looks like:
```rust ```rust
rocket::ignite().catch(errors![not_found]) rocket::ignite().catch(catchers![not_found])
``` ```
Unlike request handlers, error handlers can only take 0, 1, or 2 parameters of Unlike request handlers, error handlers can only take 0, 1, or 2 parameters of

View File

@ -124,12 +124,13 @@ the standard library types including `&str`, `String`, `File`, `Option`, and
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html). [Template](https://api.rocket.rs/rocket_contrib/struct.Template.html).
The task of a `Responder` is to generate a The task of a `Responder` is to generate a
[Response](https://api.rocket.rs/rocket/response/struct.Response.html), if [`Response`](https://api.rocket.rs/rocket/response/struct.Response.html), if
possible. `Responder`s can fail with a status code. When they do, Rocket calls possible. `Responder`s can fail with a status code. When they do, Rocket calls
the corresponding `error` route, which can be declared as follows: the corresponding error catcher, a `catch` route, which can be declared as
follows:
```rust ```rust
#[error(404)] #[catch(404)]
fn not_found() -> T { ... } fn not_found() -> T { ... }
``` ```
''' '''