Add documentation (#15)
* Add documentation for Fairing * Add Guard example and documentation
This commit is contained in:
parent
35e9665628
commit
8fc8fef3eb
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rocket_cors"
|
name = "rocket_cors"
|
||||||
version = "0.0.1"
|
version = "0.1.0"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
authors = ["Yong Wen Chua <me@yongwen.xyz>"]
|
authors = ["Yong Wen Chua <me@yongwen.xyz>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
[![Build Status](https://travis-ci.org/lawliet89/rocket_cors.svg)](https://travis-ci.org/lawliet89/rocket_cors)
|
[![Build Status](https://travis-ci.org/lawliet89/rocket_cors.svg)](https://travis-ci.org/lawliet89/rocket_cors)
|
||||||
[![Dependency Status](https://dependencyci.com/github/lawliet89/rocket_cors/badge)](https://dependencyci.com/github/lawliet89/rocket_cors)
|
[![Dependency Status](https://dependencyci.com/github/lawliet89/rocket_cors/badge)](https://dependencyci.com/github/lawliet89/rocket_cors)
|
||||||
[![Repository](https://img.shields.io/github/tag/lawliet89/rocket_cors.svg)](https://github.com/lawliet89/rocket_cors)
|
[![Repository](https://img.shields.io/github/tag/lawliet89/rocket_cors.svg)](https://github.com/lawliet89/rocket_cors)
|
||||||
<!-- [![Crates.io](https://img.shields.io/crates/v/rocket_cors.svg)](https://crates.io/crates/rocket_cors) -->
|
[![Crates.io](https://img.shields.io/crates/v/rocket_cors.svg)](https://crates.io/crates/rocket_cors)
|
||||||
<!-- [![Documentation](https://docs.rs/rocket_cors/badge.svg)](https://docs.rs/rocket_cors) -->
|
|
||||||
|
|
||||||
- Documentation: stable | [master branch](https://lawliet89.github.io/rocket_cors)
|
- Documentation: [master branch](https://lawliet89.github.io/rocket_cors)
|
||||||
|
|
||||||
Cross-origin resource sharing (CORS) for [Rocket](https://rocket.rs/) applications
|
Cross-origin resource sharing (CORS) for [Rocket](https://rocket.rs/) applications
|
||||||
|
|
||||||
|
@ -27,11 +26,11 @@ might work, but it's not guaranteed.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
<!-- Add the following to Cargo.toml:
|
Add the following to Cargo.toml:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
rocket_cors = "0.1.0"
|
rocket_cors = "0.1.0"
|
||||||
``` -->
|
```
|
||||||
|
|
||||||
To use the latest `master` branch, for example:
|
To use the latest `master` branch, for example:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#![feature(plugin, custom_derive)]
|
||||||
|
#![plugin(rocket_codegen)]
|
||||||
|
extern crate rocket;
|
||||||
|
extern crate rocket_cors;
|
||||||
|
|
||||||
|
use rocket::http::Method;
|
||||||
|
use rocket_cors::AllOrSome;
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
fn cors<'a>() -> &'a str {
|
||||||
|
"Hello CORS"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (allowed_origins, failed_origins) = AllOrSome::new_from_str_list(&["https://www.acme.com"]);
|
||||||
|
assert!(failed_origins.is_empty());
|
||||||
|
|
||||||
|
// You can also deserialize this
|
||||||
|
let options = rocket_cors::Cors {
|
||||||
|
allowed_origins: allowed_origins,
|
||||||
|
allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||||
|
allowed_headers: AllOrSome::Some(
|
||||||
|
["Authorization", "Accept"]
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_string().into())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
allow_credentials: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket::ignite()
|
||||||
|
.mount("/", routes![cors])
|
||||||
|
.attach(options)
|
||||||
|
.launch();
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#![feature(plugin, custom_derive)]
|
||||||
|
#![plugin(rocket_codegen)]
|
||||||
|
extern crate rocket;
|
||||||
|
extern crate rocket_cors;
|
||||||
|
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use rocket::Response;
|
||||||
|
use rocket::http::Method;
|
||||||
|
use rocket_cors::{Guard, AllOrSome, Responder};
|
||||||
|
|
||||||
|
/// Using a `Responder` -- the usual way you would use this
|
||||||
|
#[get("/")]
|
||||||
|
fn responder(cors: Guard) -> Responder<&str> {
|
||||||
|
cors.responder("Hello CORS!")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// You need to define an OPTIONS route for preflight checks.
|
||||||
|
/// These routes can just return the unit type `()`
|
||||||
|
#[options("/")]
|
||||||
|
fn responder_options(cors: Guard) -> Responder<()> {
|
||||||
|
cors.responder(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Using a `Response` instead of a `Responder`. You generally won't have to do this.
|
||||||
|
#[get("/responder")]
|
||||||
|
fn response(cors: Guard) -> Response {
|
||||||
|
let mut response = Response::new();
|
||||||
|
response.set_sized_body(Cursor::new("Hello CORS!"));
|
||||||
|
cors.response(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// You need to define an OPTIONS route for preflight checks.
|
||||||
|
/// These routes can just return the unit type `()`
|
||||||
|
#[options("/responder")]
|
||||||
|
fn response_options(cors: Guard) -> Response {
|
||||||
|
let response = Response::new();
|
||||||
|
cors.response(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (allowed_origins, failed_origins) = AllOrSome::new_from_str_list(&["https://www.acme.com"]);
|
||||||
|
assert!(failed_origins.is_empty());
|
||||||
|
|
||||||
|
// You can also deserialize this
|
||||||
|
let options = rocket_cors::Cors {
|
||||||
|
allowed_origins: allowed_origins,
|
||||||
|
allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||||
|
allowed_headers: AllOrSome::Some(
|
||||||
|
["Authorization", "Accept"]
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_string().into())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
allow_credentials: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket::ignite()
|
||||||
|
.mount("/", routes![responder, responder_options, response, response_options])
|
||||||
|
.manage(options)
|
||||||
|
.launch();
|
||||||
|
}
|
216
src/lib.rs
216
src/lib.rs
|
@ -1,10 +1,9 @@
|
||||||
//! [![Build Status](https://travis-ci.org/lawliet89/rocket_cors.svg)](https://travis-ci.org/lawliet89/rocket_cors)
|
//! [![Build Status](https://travis-ci.org/lawliet89/rocket_cors.svg)](https://travis-ci.org/lawliet89/rocket_cors)
|
||||||
//! [![Dependency Status](https://dependencyci.com/github/lawliet89/rocket_cors/badge)](https://dependencyci.com/github/lawliet89/rocket_cors)
|
//! [![Dependency Status](https://dependencyci.com/github/lawliet89/rocket_cors/badge)](https://dependencyci.com/github/lawliet89/rocket_cors)
|
||||||
//! [![Repository](https://img.shields.io/github/tag/lawliet89/rocket_cors.svg)](https://github.com/lawliet89/rocket_cors)
|
//! [![Repository](https://img.shields.io/github/tag/lawliet89/rocket_cors.svg)](https://github.com/lawliet89/rocket_cors)
|
||||||
//! <!-- [![Crates.io](https://img.shields.io/crates/v/rocket_cors.svg)](https://crates.io/crates/rocket_cors) -->
|
//! [![Crates.io](https://img.shields.io/crates/v/rocket_cors.svg)](https://crates.io/crates/rocket_cors)
|
||||||
//! <!-- [![Documentation](https://docs.rs/rocket_cors/badge.svg)](https://docs.rs/rocket_cors) -->
|
|
||||||
//!
|
//!
|
||||||
//! - Documentation: stable | [master branch](https://lawliet89.github.io/rocket_cors)
|
//! - Documentation: [master branch](https://lawliet89.github.io/rocket_cors)
|
||||||
//!
|
//!
|
||||||
//! Cross-origin resource sharing (CORS) for [Rocket](https://rocket.rs/) applications
|
//! Cross-origin resource sharing (CORS) for [Rocket](https://rocket.rs/) applications
|
||||||
//!
|
//!
|
||||||
|
@ -25,11 +24,11 @@
|
||||||
//!
|
//!
|
||||||
//! ## Installation
|
//! ## Installation
|
||||||
//!
|
//!
|
||||||
//! <!-- Add the following to Cargo.toml:
|
//! Add the following to Cargo.toml:
|
||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! rocket_cors = "0.0.6"
|
//! rocket_cors = "0.1.0"
|
||||||
//! ``` -->
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! To use the latest `master` branch, for example:
|
//! To use the latest `master` branch, for example:
|
||||||
//!
|
//!
|
||||||
|
@ -37,6 +36,194 @@
|
||||||
//! rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
|
//! rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! ## Usage
|
||||||
|
//!
|
||||||
|
//! Before you can add CORS responses to your application, you need to create a `Cors` struct that
|
||||||
|
//! will hold the settings.
|
||||||
|
//!
|
||||||
|
//! Each of the examples can be run off the repository via `cargo run --example xxx` where `xxx` is
|
||||||
|
//!
|
||||||
|
//! - `fairing`
|
||||||
|
//! - `guard`
|
||||||
|
//! - `manual`
|
||||||
|
//!
|
||||||
|
//! ### `Cors` Struct
|
||||||
|
//!
|
||||||
|
//! The [`Cors` struct](struct.Cors.html) contains the settings for CORS requests to be validated
|
||||||
|
//! and for responses to be generated. Defaults are defined for every field in the struct, and
|
||||||
|
//! are documented on the [`Cors` struct](struct.Cors.html) page. You can also deserialize
|
||||||
|
//! the struct from some format like JSON, YAML or TOML.
|
||||||
|
//!
|
||||||
|
//! ### Three modes of operation
|
||||||
|
//!
|
||||||
|
//! You can add CORS to your routes via one of three ways, in descending order of ease and in
|
||||||
|
//! ascending order of flexibility.
|
||||||
|
//!
|
||||||
|
//! - Fairing (should only used exclusively)
|
||||||
|
//! - Request Guard
|
||||||
|
//! - Truly Manual (not supported yet, [#13](https://github.com/lawliet89/rocket_cors/issues/13))
|
||||||
|
//!
|
||||||
|
//! Unfortunately, you cannot mix and match Fairing with any other of the methods, due to the
|
||||||
|
//! limitation of Rocket's fairing API. That is, the checks for Fairing will always happen first,
|
||||||
|
//! and if they fail, the route is never executed and so your guard or manual checks will never
|
||||||
|
//! get executed.
|
||||||
|
//!
|
||||||
|
//! You can, however, mix and match guards and manual checks.
|
||||||
|
//!
|
||||||
|
//! In summary:
|
||||||
|
//!
|
||||||
|
//! | | Fairing | Request Guard | Manual |
|
||||||
|
//! |:---------------------------------------:|:-------:|:-------------:|:------:|
|
||||||
|
//! | Must apply to all routes | ✔ | ✗ | ✗ |
|
||||||
|
//! | Different settings for different routes | ✗ | ✗ | ✔ |
|
||||||
|
//! | Must define OPTIONS route | ✗ | ✔ | ✔ |
|
||||||
|
//!
|
||||||
|
//! ### Fairing
|
||||||
|
//!
|
||||||
|
//! Fairing is the easiest to use and also the most inflexible. You don't have to define `OPTIONS`
|
||||||
|
//! routes for your application, and the checks are done transparently.
|
||||||
|
//!
|
||||||
|
//! However, you can only have one set of settings that must apply to all routes. You cannot opt
|
||||||
|
//! any route out of CORS checks.
|
||||||
|
//!
|
||||||
|
//! To use this, simply create a [`Cors` struct](struct.Cors.html) and then
|
||||||
|
//! [`attach`](https://api.rocket.rs/rocket/struct.Rocket.html#method.attach) it to Rocket.
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! #![feature(plugin, custom_derive)]
|
||||||
|
//! #![plugin(rocket_codegen)]
|
||||||
|
//! extern crate rocket;
|
||||||
|
//! extern crate rocket_cors;
|
||||||
|
//!
|
||||||
|
//! use rocket::http::Method;
|
||||||
|
//! use rocket_cors::AllOrSome;
|
||||||
|
//!
|
||||||
|
//! #[get("/")]
|
||||||
|
//! fn cors<'a>() -> &'a str {
|
||||||
|
//! "Hello CORS"
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn main() {
|
||||||
|
//! let (allowed_origins, failed_origins) = AllOrSome::new_from_str_list(&["https://www.acme.com"]);
|
||||||
|
//! assert!(failed_origins.is_empty());
|
||||||
|
//!
|
||||||
|
//! // You can also deserialize this
|
||||||
|
//! let options = rocket_cors::Cors {
|
||||||
|
//! allowed_origins: allowed_origins,
|
||||||
|
//! allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||||
|
//! allowed_headers: AllOrSome::Some(
|
||||||
|
//! ["Authorization", "Accept"]
|
||||||
|
//! .into_iter()
|
||||||
|
//! .map(|s| s.to_string().into())
|
||||||
|
//! .collect(),
|
||||||
|
//! ),
|
||||||
|
//! allow_credentials: true,
|
||||||
|
//! ..Default::default()
|
||||||
|
//! };
|
||||||
|
//!
|
||||||
|
//! rocket::ignite()
|
||||||
|
//! .mount("/", routes![cors])
|
||||||
|
//! .attach(options)
|
||||||
|
//! .launch();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ### Request Guard
|
||||||
|
//!
|
||||||
|
//! Using request guard requires you to sacrifice the convenience of Fairings for being able to
|
||||||
|
//! opt some routes out of CORS checks and enforcement. _BUT_ you are still restricted to only
|
||||||
|
//! one set of CORS settings and you will now have to define `OPTIONS` routes for all the routes
|
||||||
|
//! you want to have CORS checks on. The `OPTIONS` routes are used for CORS preflight checks.
|
||||||
|
//!
|
||||||
|
//! You will have to do the following:
|
||||||
|
//!
|
||||||
|
//! - Create a [`Cors` struct](struct.Cors.html) and during Rocket's ignite, add the struct to
|
||||||
|
//! Rocket's [managed state](https://rocket.rs/guide/state/#managed-state).
|
||||||
|
//! - For all the routes that you want to enforce CORS on, you have to define a `OPTIONS` route
|
||||||
|
//! for the path. You can use [dynamic segments](https://rocket.rs/guide/requests/#dynamic-segments)
|
||||||
|
//! to reduce the number of routes you have to define.
|
||||||
|
//! - Then in all the routes you want to enforce CORS on, add a
|
||||||
|
//! [Request Guard](https://rocket.rs/guide/requests/#request-guards) for the
|
||||||
|
//! [`Guard`](struct.Guard.html) struct in the route arguments. You should not wrap this in an
|
||||||
|
//! `Option` or `Result` because the guard will let non-CORS requests through and will take over
|
||||||
|
//! error handling in case of errors.
|
||||||
|
//! - In your routes, to add CORS headers to your responses, use the appropriate functions on the
|
||||||
|
//! [`Guard`](struct.Guard.html) for a `Response` or a `Responder`.
|
||||||
|
//!
|
||||||
|
//! You can mix this with the "manual" checks, but whichever `Response` is the last merged will
|
||||||
|
//! overwrite the previous CORS headers.
|
||||||
|
//!
|
||||||
|
//! ```rust,no_run
|
||||||
|
//! #![feature(plugin, custom_derive)]
|
||||||
|
//! #![plugin(rocket_codegen)]
|
||||||
|
//! extern crate rocket;
|
||||||
|
//! extern crate rocket_cors;
|
||||||
|
//!
|
||||||
|
//! use std::io::Cursor;
|
||||||
|
//!
|
||||||
|
//! use rocket::Response;
|
||||||
|
//! use rocket::http::Method;
|
||||||
|
//! use rocket_cors::{Guard, AllOrSome, Responder};
|
||||||
|
//!
|
||||||
|
//! /// Using a `Responder` -- the usual way you would use this
|
||||||
|
//! #[get("/")]
|
||||||
|
//! fn responder(cors: Guard) -> Responder<&str> {
|
||||||
|
//! cors.responder("Hello CORS!")
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! /// You need to define an OPTIONS route for preflight checks.
|
||||||
|
//! /// These routes can just return the unit type `()`
|
||||||
|
//! #[options("/")]
|
||||||
|
//! fn responder_options(cors: Guard) -> Responder<()> {
|
||||||
|
//! cors.responder(())
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! /// Using a `Response` instead of a `Responder`. You generally won't have to do this.
|
||||||
|
//! #[get("/responder")]
|
||||||
|
//! fn response(cors: Guard) -> Response {
|
||||||
|
//! let mut response = Response::new();
|
||||||
|
//! response.set_sized_body(Cursor::new("Hello CORS!"));
|
||||||
|
//! cors.response(response)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! /// You need to define an OPTIONS route for preflight checks.
|
||||||
|
//! /// These routes can just return the unit type `()`
|
||||||
|
//! #[options("/responder")]
|
||||||
|
//! fn response_options(cors: Guard) -> Response {
|
||||||
|
//! let response = Response::new();
|
||||||
|
//! cors.response(response)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn main() {
|
||||||
|
//! let (allowed_origins, failed_origins) = AllOrSome::new_from_str_list(&["https://www.acme.com"]);
|
||||||
|
//! assert!(failed_origins.is_empty());
|
||||||
|
//!
|
||||||
|
//! // You can also deserialize this
|
||||||
|
//! let options = rocket_cors::Cors {
|
||||||
|
//! allowed_origins: allowed_origins,
|
||||||
|
//! allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||||
|
//! allowed_headers: AllOrSome::Some(
|
||||||
|
//! ["Authorization", "Accept"]
|
||||||
|
//! .into_iter()
|
||||||
|
//! .map(|s| s.to_string().into())
|
||||||
|
//! .collect(),
|
||||||
|
//! ),
|
||||||
|
//! allow_credentials: true,
|
||||||
|
//! ..Default::default()
|
||||||
|
//! };
|
||||||
|
//!
|
||||||
|
//! rocket::ignite()
|
||||||
|
//! .mount("/", routes![responder, responder_options, response, response_options])
|
||||||
|
//! .manage(options)
|
||||||
|
//! .launch();
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ## Truly Manual
|
||||||
|
//!
|
||||||
|
//! This is not supported yet. See [#13](https://github.com/lawliet89/rocket_cors/issues/13).
|
||||||
|
|
||||||
#![allow(
|
#![allow(
|
||||||
legacy_directory_ownership,
|
legacy_directory_ownership,
|
||||||
|
@ -119,9 +306,6 @@ mod fairing;
|
||||||
|
|
||||||
pub mod headers;
|
pub mod headers;
|
||||||
|
|
||||||
// Public exports
|
|
||||||
pub use headers::Url;
|
|
||||||
|
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -136,7 +320,7 @@ use rocket::response;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use headers::{HeaderFieldName, HeaderFieldNamesSet, Origin, AccessControlRequestHeaders,
|
use headers::{HeaderFieldName, HeaderFieldNamesSet, Origin, AccessControlRequestHeaders,
|
||||||
AccessControlRequestMethod};
|
AccessControlRequestMethod, Url};
|
||||||
|
|
||||||
/// Errors during operations
|
/// Errors during operations
|
||||||
///
|
///
|
||||||
|
@ -367,7 +551,8 @@ impl<'de> Deserialize<'de> for Method {
|
||||||
|
|
||||||
/// Response generator and [Fairing](https://rocket.rs/guide/fairings/) for CORS
|
/// Response generator and [Fairing](https://rocket.rs/guide/fairings/) for CORS
|
||||||
///
|
///
|
||||||
/// This struct can be as Fairing or in an ad-hoc manner to generate CORS response.
|
/// This struct can be as Fairing or in an ad-hoc manner to generate CORS response. See the
|
||||||
|
/// documentation at the [crate root](index.html) for usage information.
|
||||||
///
|
///
|
||||||
/// You create a new copy of this struct by defining the configurations in the fields below.
|
/// You create a new copy of this struct by defining the configurations in the fields below.
|
||||||
/// This struct can also be deserialized by serde.
|
/// This struct can also be deserialized by serde.
|
||||||
|
@ -709,8 +894,13 @@ impl Response {
|
||||||
|
|
||||||
|
|
||||||
/// A [request guard](https://rocket.rs/guide/requests/#request-guards) to check CORS headers
|
/// A [request guard](https://rocket.rs/guide/requests/#request-guards) to check CORS headers
|
||||||
/// before a route is run. Will not execute the route if checks fail
|
/// before a route is run. Will not execute the route if checks fail.
|
||||||
///
|
///
|
||||||
|
/// See the documentation at the [crate root](index.html) for usage information.
|
||||||
|
///
|
||||||
|
/// You should not wrap this in an
|
||||||
|
/// `Option` or `Result` because the guard will let non-CORS requests through and will take over
|
||||||
|
/// error handling in case of errors.
|
||||||
/// In essence, this is just a wrapper around `Response` with a `'r` borrowed lifetime so users
|
/// In essence, this is just a wrapper around `Response` with a `'r` borrowed lifetime so users
|
||||||
/// don't have to keep specifying the lifetimes in their routes
|
/// don't have to keep specifying the lifetimes in their routes
|
||||||
pub struct Guard<'r> {
|
pub struct Guard<'r> {
|
||||||
|
@ -772,6 +962,8 @@ impl<'a, 'r> FromRequest<'a, 'r> for Guard<'r> {
|
||||||
/// - `Access-Control-Allow-Methods`
|
/// - `Access-Control-Allow-Methods`
|
||||||
/// - `Access-Control-Allow-Headers`
|
/// - `Access-Control-Allow-Headers`
|
||||||
/// - `Vary`
|
/// - `Vary`
|
||||||
|
///
|
||||||
|
/// See the documentation at the [crate root](index.html) for usage information.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Responder<'r, R> {
|
pub struct Responder<'r, R> {
|
||||||
responder: R,
|
responder: R,
|
||||||
|
|
Loading…
Reference in New Issue