Use request local cache for fairing implementation (#50)

This commit is contained in:
Yong Wen Chua 2018-11-01 14:44:28 +08:00 committed by GitHub
parent 21444e90c4
commit 9cb16ba01d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 56 deletions

View File

@ -1,47 +1,19 @@
//! Fairing implementation //! Fairing implementation
use std::str::FromStr;
use log::{error, info, log}; use log::{error, info, log};
use rocket::http::{self, uri::Origin, Header, Status}; use rocket::http::{self, uri::Origin, Status};
use rocket::{self, error_, info_, log_, Outcome, Request}; use rocket::{self, error_, info_, log_, Outcome, Request};
use crate::{ use crate::{
actual_request_response, origin, preflight_response, request_headers, validate, Cors, Error, actual_request_response, origin, preflight_response, request_headers, validate, Cors, Error,
}; };
/// An injected header to quickly give the result of CORS /// Request Local State to store CORS validation results
static CORS_HEADER: &str = "ROCKET-CORS"; enum CorsValidation {
enum InjectedHeader {
Success, Success,
Failure, Failure,
} }
impl InjectedHeader {
fn to_str(&self) -> &'static str {
match *self {
InjectedHeader::Success => "Success",
InjectedHeader::Failure => "Failure",
}
}
}
impl FromStr for InjectedHeader {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
match s {
"Success" => Ok(InjectedHeader::Success),
"Failure" => Ok(InjectedHeader::Failure),
other => {
error_!(
"Unknown injected header encountered: {}\nThis is probably a bug.",
other
);
Err(Error::UnknownInjectedHeader)
}
}
}
}
/// Route for Fairing error handling /// Route for Fairing error handling
pub(crate) fn fairing_error_route<'r>( pub(crate) fn fairing_error_route<'r>(
request: &'r Request, request: &'r Request,
@ -71,11 +43,6 @@ fn route_to_fairing_error_handler(options: &Cors, status: u16, request: &mut Req
request.set_uri(origin); request.set_uri(origin);
} }
/// Inject a header into the Request with result
fn inject_request_header(header: &InjectedHeader, request: &mut Request) {
request.replace_header(Header::new(CORS_HEADER, header.to_str()));
}
fn on_response_wrapper( fn on_response_wrapper(
options: &Cors, options: &Cors,
request: &Request, request: &Request,
@ -89,14 +56,9 @@ fn on_response_wrapper(
Some(origin) => origin, Some(origin) => origin,
}; };
// Get validation result from injected header let result = request.local_cache(|| unreachable!("This should not be executed so late"));
let injected_header = request
.headers()
.get_one(CORS_HEADER)
.ok_or_else(|| Error::MissingInjectedHeader)?;
let result = InjectedHeader::from_str(injected_header)?;
if let InjectedHeader::Failure = result { if let &CorsValidation::Failure = result {
// Nothing else for us to do // Nothing else for us to do
return Ok(()); return Ok(());
} }
@ -151,17 +113,17 @@ impl rocket::fairing::Fairing for Cors {
} }
fn on_request(&self, request: &mut Request, _: &rocket::Data) { fn on_request(&self, request: &mut Request, _: &rocket::Data) {
let injected_header = match validate(self, request) { let result = match validate(self, request) {
Ok(_) => InjectedHeader::Success, Ok(_) => CorsValidation::Success,
Err(err) => { Err(err) => {
error_!("CORS Error: {}", err); error_!("CORS Error: {}", err);
let status = err.status(); let status = err.status();
route_to_fairing_error_handler(self, status.code, request); route_to_fairing_error_handler(self, status.code, request);
InjectedHeader::Failure CorsValidation::Failure
} }
}; };
inject_request_header(&injected_header, request); let _ = request.local_cache(|| result);
} }
fn on_response(&self, request: &Request, response: &mut rocket::Response) { fn on_response(&self, request: &Request, response: &mut rocket::Response) {

View File

@ -637,9 +637,6 @@ pub enum Error {
/// The `on_response` handler of Fairing could not find the injected header from the Request. /// The `on_response` handler of Fairing could not find the injected header from the Request.
/// Either some other fairing has removed it, or this is a bug. /// Either some other fairing has removed it, or this is a bug.
MissingInjectedHeader, MissingInjectedHeader,
/// The `on_response` handler of Fairing found an unknown injected header value from the
/// Request. Either some other fairing has modified it, or this is a bug.
UnknownInjectedHeader,
} }
impl Error { impl Error {
@ -651,8 +648,7 @@ impl Error {
| Error::HeadersNotAllowed => Status::Forbidden, | Error::HeadersNotAllowed => Status::Forbidden,
Error::CredentialsWithWildcardOrigin Error::CredentialsWithWildcardOrigin
| Error::MissingCorsInRocketState | Error::MissingCorsInRocketState
| Error::MissingInjectedHeader | Error::MissingInjectedHeader => Status::InternalServerError,
| Error::UnknownInjectedHeader => Status::InternalServerError,
_ => Status::BadRequest, _ => Status::BadRequest,
} }
} }
@ -688,10 +684,6 @@ impl error::Error for Error {
"The `on_response` handler of Fairing could not find the injected header from the \ "The `on_response` handler of Fairing could not find the injected header from the \
Request. Either some other fairing has removed it, or this is a bug." Request. Either some other fairing has removed it, or this is a bug."
} }
Error::UnknownInjectedHeader => {
"The `on_response` handler of Fairing found an unknown injected header value from \
the Request. Either some other fairing has modified it, or this is a bug."
}
} }
} }