mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-04-20 06:54:46 +00:00
update to gotham 0.5 and start using rustfmt
This commit is contained in:
parent
5317e50961
commit
d55b0897e9
39 changed files with 1798 additions and 2095 deletions
102
src/cors.rs
102
src/cors.rs
|
@ -4,22 +4,19 @@ use gotham::{
|
|||
helpers::http::response::create_empty_response,
|
||||
hyper::{
|
||||
header::{
|
||||
ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,
|
||||
ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_MAX_AGE, ACCESS_CONTROL_REQUEST_METHOD, ORIGIN, VARY,
|
||||
HeaderMap, HeaderName, HeaderValue
|
||||
HeaderMap, HeaderName, HeaderValue, ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS,
|
||||
ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_MAX_AGE,
|
||||
ACCESS_CONTROL_REQUEST_METHOD, ORIGIN, VARY
|
||||
},
|
||||
Body, Method, Response, StatusCode
|
||||
},
|
||||
middleware::Middleware,
|
||||
pipeline::chain::PipelineHandleChain,
|
||||
router::builder::*,
|
||||
state::{FromState, State},
|
||||
state::{FromState, State}
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use std::{
|
||||
panic::RefUnwindSafe,
|
||||
pin::Pin
|
||||
};
|
||||
use std::{panic::RefUnwindSafe, pin::Pin};
|
||||
|
||||
/**
|
||||
Specify the allowed origins of the request. It is up to the browser to check the validity of the
|
||||
|
@ -27,8 +24,7 @@ origin. This, when sent to the browser, will indicate whether or not the request
|
|||
allowed to make the request.
|
||||
*/
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Origin
|
||||
{
|
||||
pub enum Origin {
|
||||
/// Do not send any `Access-Control-Allow-Origin` headers.
|
||||
None,
|
||||
/// Send `Access-Control-Allow-Origin: *`. Note that browser will not send credentials.
|
||||
|
@ -39,19 +35,15 @@ pub enum Origin
|
|||
Copy
|
||||
}
|
||||
|
||||
impl Default for Origin
|
||||
{
|
||||
fn default() -> Self
|
||||
{
|
||||
impl Default for Origin {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
impl Origin
|
||||
{
|
||||
impl Origin {
|
||||
/// Get the header value for the `Access-Control-Allow-Origin` header.
|
||||
fn header_value(&self, state : &State) -> Option<HeaderValue>
|
||||
{
|
||||
fn header_value(&self, state: &State) -> Option<HeaderValue> {
|
||||
match self {
|
||||
Self::None => None,
|
||||
Self::Star => Some("*".parse().unwrap()),
|
||||
|
@ -126,23 +118,21 @@ gotham::start("127.0.0.1:8080", build_router((), pipeline_set, |route| {
|
|||
[`State`]: ../gotham/state/struct.State.html
|
||||
*/
|
||||
#[derive(Clone, Debug, Default, NewMiddleware, StateData)]
|
||||
pub struct CorsConfig
|
||||
{
|
||||
pub struct CorsConfig {
|
||||
/// The allowed origins.
|
||||
pub origin : Origin,
|
||||
pub origin: Origin,
|
||||
/// The allowed headers.
|
||||
pub headers : Vec<HeaderName>,
|
||||
pub headers: Vec<HeaderName>,
|
||||
/// The amount of seconds that the preflight request can be cached.
|
||||
pub max_age : u64,
|
||||
pub max_age: u64,
|
||||
/// Whether or not the request may be made with supplying credentials.
|
||||
pub credentials : bool
|
||||
pub credentials: bool
|
||||
}
|
||||
|
||||
impl Middleware for CorsConfig
|
||||
{
|
||||
fn call<Chain>(self, mut state : State, chain : Chain) -> Pin<Box<HandlerFuture>>
|
||||
impl Middleware for CorsConfig {
|
||||
fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
|
||||
where
|
||||
Chain : FnOnce(State) -> Pin<Box<HandlerFuture>>
|
||||
Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>
|
||||
{
|
||||
state.put(self);
|
||||
chain(state)
|
||||
|
@ -161,35 +151,31 @@ For further information on CORS, read https://developer.mozilla.org/en-US/docs/W
|
|||
|
||||
[`CorsConfig`]: ./struct.CorsConfig.html
|
||||
*/
|
||||
pub fn handle_cors(state : &State, res : &mut Response<Body>)
|
||||
{
|
||||
pub fn handle_cors(state: &State, res: &mut Response<Body>) {
|
||||
let config = CorsConfig::try_borrow_from(state);
|
||||
let headers = res.headers_mut();
|
||||
|
||||
|
||||
// non-preflight requests require the Access-Control-Allow-Origin header
|
||||
if let Some(header) = config.and_then(|cfg| cfg.origin.header_value(state))
|
||||
{
|
||||
if let Some(header) = config.and_then(|cfg| cfg.origin.header_value(state)) {
|
||||
headers.insert(ACCESS_CONTROL_ALLOW_ORIGIN, header);
|
||||
}
|
||||
|
||||
// if the origin is copied over, we should tell the browser by specifying the Vary header
|
||||
if matches!(config.map(|cfg| &cfg.origin), Some(Origin::Copy))
|
||||
{
|
||||
if matches!(config.map(|cfg| &cfg.origin), Some(Origin::Copy)) {
|
||||
let vary = headers.get(VARY).map(|vary| format!("{},Origin", vary.to_str().unwrap()));
|
||||
headers.insert(VARY, vary.as_deref().unwrap_or("Origin").parse().unwrap());
|
||||
}
|
||||
|
||||
// if we allow credentials, tell the browser
|
||||
if config.map(|cfg| cfg.credentials).unwrap_or(false)
|
||||
{
|
||||
if config.map(|cfg| cfg.credentials).unwrap_or(false) {
|
||||
headers.insert(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true".parse().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
/// Add CORS routing for your path. This is required for handling preflight requests.
|
||||
///
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use gotham::{hyper::{Body, Method, Response}, router::builder::*};
|
||||
/// # use gotham_restful::*;
|
||||
|
@ -206,16 +192,15 @@ pub fn handle_cors(state : &State, res : &mut Response<Body>)
|
|||
/// ```
|
||||
pub trait CorsRoute<C, P>
|
||||
where
|
||||
C : PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
P : RefUnwindSafe + Send + Sync + 'static
|
||||
C: PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
P: RefUnwindSafe + Send + Sync + 'static
|
||||
{
|
||||
/// Handle a preflight request on `path` for `method`. To configure the behaviour, use
|
||||
/// [`CorsConfig`](struct.CorsConfig.html).
|
||||
fn cors(&mut self, path : &str, method : Method);
|
||||
fn cors(&mut self, path: &str, method: Method);
|
||||
}
|
||||
|
||||
fn cors_preflight_handler(state : State) -> (State, Response<Body>)
|
||||
{
|
||||
fn cors_preflight_handler(state: State) -> (State, Response<Body>) {
|
||||
let config = CorsConfig::try_borrow_from(&state);
|
||||
|
||||
// prepare the response
|
||||
|
@ -223,43 +208,40 @@ fn cors_preflight_handler(state : State) -> (State, Response<Body>)
|
|||
let headers = res.headers_mut();
|
||||
|
||||
// copy the request method over to the response
|
||||
let method = HeaderMap::borrow_from(&state).get(ACCESS_CONTROL_REQUEST_METHOD).unwrap().clone();
|
||||
let method = HeaderMap::borrow_from(&state)
|
||||
.get(ACCESS_CONTROL_REQUEST_METHOD)
|
||||
.unwrap()
|
||||
.clone();
|
||||
headers.insert(ACCESS_CONTROL_ALLOW_METHODS, method);
|
||||
|
||||
// if we allow any headers, put them in
|
||||
if let Some(hdrs) = config.map(|cfg| &cfg.headers)
|
||||
{
|
||||
if hdrs.len() > 0
|
||||
{
|
||||
if let Some(hdrs) = config.map(|cfg| &cfg.headers) {
|
||||
if hdrs.len() > 0 {
|
||||
// TODO do we want to return all headers or just those asked by the browser?
|
||||
headers.insert(ACCESS_CONTROL_ALLOW_HEADERS, hdrs.iter().join(",").parse().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
// set the max age for the preflight cache
|
||||
if let Some(age) = config.map(|cfg| cfg.max_age)
|
||||
{
|
||||
if let Some(age) = config.map(|cfg| cfg.max_age) {
|
||||
headers.insert(ACCESS_CONTROL_MAX_AGE, age.into());
|
||||
}
|
||||
|
||||
// make sure the browser knows that this request was based on the method
|
||||
headers.insert(VARY, "Access-Control-Request-Method".parse().unwrap());
|
||||
|
||||
|
||||
handle_cors(&state, &mut res);
|
||||
(state, res)
|
||||
}
|
||||
|
||||
impl<D, C, P> CorsRoute<C, P> for D
|
||||
where
|
||||
D : DrawRoutes<C, P>,
|
||||
C : PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
P : RefUnwindSafe + Send + Sync + 'static
|
||||
D: DrawRoutes<C, P>,
|
||||
C: PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
P: RefUnwindSafe + Send + Sync + 'static
|
||||
{
|
||||
fn cors(&mut self, path : &str, method : Method)
|
||||
{
|
||||
fn cors(&mut self, path: &str, method: Method) {
|
||||
let matcher = AccessControlRequestMethodMatcher::new(method);
|
||||
self.options(path)
|
||||
.extend_route_matcher(matcher)
|
||||
.to(cors_preflight_handler);
|
||||
self.options(path).extend_route_matcher(matcher).to(cors_preflight_handler);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue