Rocket/lib/tests/precise-content-type-matching.rs
Sergio Benitez cc22836867 Precisely route formats. Make 'content_type' an 'Option' in 'Request'.
This commit changes the routing algorithm. In particular, it enforces
precise matching of formats. With this change, a route with a specified
format only matches requests that have the same format specified. A
route with no format specified matches any request's format. This is
contrast to the previous behavior, where a route without a specified
format would match requests regardless of their format or whether one
was specified.

This commit also changes the following:
  * The return type of the 'content_type' method of 'Request' is now
    'Option<ContentType>'.
  * The 'ContentType' request guard forwards when the request has no
    specified ContentType.
  * The 'add_header' and 'replace_header' methods take the header
    argument generically.

Closes #120.
2017-02-01 03:12:24 -08:00

75 lines
2.1 KiB
Rust

#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[post("/", format = "application/json")]
fn specified() -> &'static str {
"specified"
}
#[post("/", rank = 2)]
fn unspecified() -> &'static str {
"unspecified"
}
#[post("/", format = "application/json")]
fn specified_json() -> &'static str {
"specified_json"
}
#[post("/", format = "text/html")]
fn specified_html() -> &'static str {
"specified_html"
}
#[cfg(feature = "testing")]
mod tests {
use super::*;
use rocket::Rocket;
use rocket::testing::MockRequest;
use rocket::http::Method::*;
use rocket::http::{Status, ContentType};
fn rocket() -> Rocket {
rocket::ignite()
.mount("/first", routes![specified, unspecified])
.mount("/second", routes![specified_json, specified_html])
}
macro_rules! check_dispatch {
($mount:expr, $ct:expr, $body:expr) => (
let rocket = rocket();
let mut req = MockRequest::new(Post, $mount);
let ct: Option<ContentType> = $ct;
if let Some(ct) = ct {
req.add_header(ct);
}
let mut response = req.dispatch_with(&rocket);
let body_str = response.body().and_then(|b| b.into_string());
let body: Option<&'static str> = $body;
match body {
Some(string) => assert_eq!(body_str, Some(string.to_string())),
None => assert_eq!(response.status(), Status::NotFound)
}
)
}
#[test]
fn exact_match_or_forward() {
check_dispatch!("/first", Some(ContentType::JSON), Some("specified"));
check_dispatch!("/first", None, Some("unspecified"));
check_dispatch!("/first", Some(ContentType::HTML), Some("unspecified"));
}
#[test]
fn exact_match_or_none() {
check_dispatch!("/second", Some(ContentType::JSON), Some("specified_json"));
check_dispatch!("/second", Some(ContentType::HTML), Some("specified_html"));
check_dispatch!("/second", Some(ContentType::CSV), None);
check_dispatch!("/second", None, None);
}
}