Rocket/core/lib/tests/forward-includes-error-1560.rs
Benedikt Weber 055ad107df Allow status customization in 'Forward' outcomes.
Prior to this commit, all forward outcomes resulted in a 404. This
commit changes request and data guards so that they are able to provide
a `Status` on `Forward` outcomes. The router uses this status, if the
final outcome is to forward, to identify the catcher to invoke.

The net effect is that guards can now customize the status code of a
forward and thus the error catcher invoked if the final outcome of a
request is to forward.

Resolves #1560.
2023-04-11 12:47:20 -07:00

80 lines
2.3 KiB
Rust

#[macro_use] extern crate rocket;
use rocket::http::Status;
use rocket::request::{self, Request, FromRequest};
pub struct Authenticated;
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Authenticated {
type Error = std::convert::Infallible;
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
if request.headers().contains("Authenticated") {
request::Outcome::Success(Authenticated)
} else {
request::Outcome::Forward(Status::Unauthorized)
}
}
}
#[get("/one")]
pub async fn get_protected_one(_user: Authenticated) -> &'static str {
"Protected"
}
#[get("/one", rank = 2)]
pub async fn get_public_one() -> &'static str {
"Public"
}
#[get("/two")]
pub async fn get_protected_two(_user: Authenticated) -> &'static str {
"Protected"
}
mod tests {
use super::*;
use rocket::routes;
use rocket::local::blocking::Client;
use rocket::http::{Header, Status};
#[test]
fn one_protected_returned_for_authenticated() {
let rocket = rocket::build().mount("/",
routes![get_protected_one, get_public_one, get_protected_two]);
let client = Client::debug(rocket).unwrap();
let req = client.get("/one").header(Header::new("Authenticated", "true"));
let response = req.dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string(), Some("Protected".into()));
}
#[test]
fn one_public_returned_for_unauthenticated() {
let rocket = rocket::build().mount("/",
routes![get_protected_one, get_public_one, get_protected_two]);
let client = Client::debug(rocket).unwrap();
let req = client.get("/one");
let response = req.dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.into_string(), Some("Public".into()));
}
#[test]
fn two_unauthorized_returned_for_unauthenticated() {
let rocket = rocket::build().mount("/",
routes![get_protected_one, get_public_one, get_protected_two]);
let client = Client::debug(rocket).unwrap();
let req = client.get("/two");
let response = req.dispatch();
assert_eq!(response.status(), Status::Unauthorized);
}
}