Forwarding
Let’s take a closer look at the route attribute and signature pair from the last example:
#[get("/hello/<name>/<age>/<cool>")]
fn hello(name: String, age: u8, cool: bool) -> String { ... }
What if cool
isn’t a bool
? Or, what if age
isn’t a u8
? When a parameter type mismatch occurs, Rocket forwards the request to the next matching route, if there is any. This continues until a route doesn’t forward the request or there are no remaining routes to try. When there are no remaining routes, a customizable 404 error is returned.
Routes are attempted in increasing rank order. Rocket chooses a default ranking from -4 to -1, detailed in the next section, for all routes, but a route’s rank can also be manually set with the rank
attribute. To illustrate, consider the following routes:
#[get("/user/<id>")]
fn user(id: usize) -> T { ... }
#[get("/user/<id>", rank = 2)]
fn user_int(id: isize) -> T { ... }
#[get("/user/<id>", rank = 3)]
fn user_str(id: &RawStr) -> T { ... }
Notice the rank
parameters in user_int
and user_str
. If we run this application with the routes mounted at the root, requests to /user/<id>
will be routed as follows:
The
user
route matches first. If the string at the<id>
position is an unsigned integer, then theuser
handler is called. If it is not, then the request is forwarded to the next matching route:user_int
.The
user_int
route matches next. If<id>
is a signed integer,user_int
is called. Otherwise, the request is forwarded.The
user_str
route matches last. Since<id>
is a always string, the route always matches. Theuser_str
handler is called.
Forwards can be caught by using a Result
or Option
type. For example, if the type of id
in the user
function was Result<usize, &RawStr>
, then user
would never forward. An Ok
variant would indicate that <id>
was a valid usize
, while an Err
would indicate that <id>
was not a usize
. The Err
‘s value would contain the string that failed to parse as a usize
.
By the way, if you were to omit the rank
parameter in the user_str
or user_int
routes, Rocket would emit an error and abort launch, indicating that the routes collide, or can match against similar incoming requests. The rank
parameter resolves this collision.
Default Ranking
If a rank is not explicitly specified, Rocket assigns a default ranking. By default, routes with static paths and query strings have lower ranks (higher precedence) while routes with dynamic paths and without query strings have higher ranks (lower precedence). The table below describes the default ranking of a route given its properties.
static path | query string | rank | example |
---|---|---|---|
yes | yes | -4 | /hello?world=true |
yes | no | -3 | /hello |
no | yes | -2 | /<hi>?world=true |
no | no | -1 | /<hi> |