Expand description
- Documentation: master branch | stable
Cross-origin resource sharing (CORS) for Rocket applications
§Requirements
- Rocket >= 0.4
If you are using Rocket 0.3, use the 0.3.0
version of this crate.
§Installation
Add the following to Cargo.toml:
rocket_cors = "0.6.0"
To use the latest master
branch, for example:
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
§Features
By default, a serialization
feature is enabled in this crate that allows you to (de)serialize
the CorsOptions
struct that is described below. If you would like to disable this, simply
change your Cargo.toml
to:
rocket_cors = { version = "0.6.0", default-features = false }
§Usage
Before you can add CORS responses to your application, you need to create a CorsOptions
struct that will hold the settings. Then, you need to create a Cors
struct using
CorsOptions::to_cors
which will validate and optimise the settings for Rocket to use.
Each of the examples can be run off the repository via cargo run --example xxx
where xxx
is
fairing
guard
manual
§CorsOptions
Struct
The CorsOptions
struct 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 CorsOptions
page. You can also deserialize
the struct from some format like JSON, YAML or TOML when the default serialization
feature
is enabled.
§Cors
Struct
The Cors
struct is what will be used with Rocket. After creating or deserializing a
CorsOptions
struct, use CorsOptions::to_cors
to create a Cors
struct.
§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 be used exclusively)
- Request Guard
- Truly Manual
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 | ✗ | ✗ | ✔ |
May define custom OPTIONS routes | ✗ | ✔ | ✔ |
§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
from CorsOptions::to_cors
and then
attach
it to Rocket.
Refer to the example.
§Injected Route
The fairing implementation will inject a route during attachment to Rocket. This route is used to handle errors during CORS validation.
This is due to the limitation in Rocket’s Fairing
lifecycle. Ideally, we want to validate the CORS request
during on_request
, and if the validation fails, we want to stop the route from even executing
to
- prevent side effects
- prevent resource usage from unnecessary computation
The only way to do this is to hijack the request and route it to our own injected route to handle errors. Rocket does not allow Fairings to stop the processing of a route.
You can configure the behaviour of the injected route through a couple of fields in the
CorsOptions
.
§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 have to mount additional routes to catch and process OPTIONS
requests. The OPTIONS
routes are used for CORS preflight checks.
You will have to do the following:
- Create a
Cors
fromCorsOptions
and during Rocket’s ignite, add the struct to Rocket’s managed state. - For all the routes that you want to enforce CORS on, you can mount either some catch all route or define your own route for the OPTIONS verb.
- Then in all the routes you want to enforce CORS on, add a
Request Guard for the
Guard
struct in the route arguments. You should not wrap this in anOption
orResult
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
for aResponse
or aResponder
.
Refer to the example.
§Truly Manual
This mode is the most difficult to use but offers the most amount of flexibility. You might have to understand how the library works internally to know how to use this mode. In exchange, you can selectively choose which routes to offer CORS protection to, and you can mix and match CORS settings for the routes. You can combine usage of this mode with “guard” to offer a mix of ease of use and flexibility.
You really do not need to use this unless you have a truly ad-hoc need to respond to CORS
differently in a route. For example, you have a ping
endpoint that allows all origins but
the rest of your routes do not.
§Handler
This mode requires that you pass in a closure that will be lazily evaluated once a CORS request has been validated. If validation fails, the closure will not be run. You should put any code that has any side effects or with an appreciable computation cost inside this handler.
§Steps to perform:
- You will first need to have a
Cors
struct ready. This struct can be borrowed with a lifetime at least as long as'r
which is the lifetime of a Rocket request.'static
works too. In this case, you might as well use theGuard
method above and place theCors
struct in Rocket’s state. Alternatively, you can create aCors
struct directly in the route. - Your routes might need to have a
'r
lifetime and returnimpl Responder<'r>
. See below. - Using the
Cors
struct, use either theCors::respond_owned
orCors::respond_borrowed
function and pass in a handler that will be executed once CORS validation is successful. - Your handler will be passed a
Guard
which you will have to use to add CORS headers into your own response. - You will have to manually define your own
OPTIONS
routes.
§Notes about route lifetime
You might have to specify a 'r
lifetime in your routes and then return impl Responder<'r>
.
If you are not sure what to do, you can try to leave the lifetime out and then add it in
when the compiler complains.
Generally, you will need to manually annotate the lifetime for the following cases where the compiler is unable to elide the lifetime:
- Your function arguments do not borrow anything.
- Your function arguments borrow from more than one lifetime.
- Your function arguments borrow from a lifetime that is shorter than the
'r
lifetime required.
You can see examples when the lifetime annotation is required (or not) in examples/manual.rs
.
See the example.
§Mixing Guard and Manual
You can mix Guard
and Truly Manual
modes together for your application. For example, your
application might restrict the Origins that can access it, except for one ping
route that
allows all access.
See the example.
§Reference
Modules§
- headers
- CORS specific Request Headers
Structs§
- Cors
- Response generator and Fairing for CORS
- Cors
Options - Configuration options for CORS request handling.
- Guard
- A request guard to check CORS headers before a route is run. Will not execute the route if checks fail.
- Manual
Responder - A Manual Responder used in the “truly manual” mode of operation.
- Method
- A wrapper type around
rocket::http::Method
to support serialization and deserialization - Origins
- Origins that are allowed to make CORS requests.
- Responder
- A
Responder
which will simply wraps anotherResponder
with CORS headers.
Enums§
- AllOr
Some - An enum signifying that some of type T is allowed, or
All
(everything is allowed). - Error
- Errors during operations
Functions§
- catch_
all_ options_ routes - Returns “catch all” OPTIONS routes that you can mount to catch all OPTIONS request. Only works
if you have put a
Cors
struct into Rocket’s managed state.
Type Aliases§
- Allowed
Headers - A list of allowed headers
- Allowed
Methods - A list of allowed methods
- Allowed
Origins - A list of allowed origins. Either Some origins are allowed, or all origins are allowed.