From c53f133bd7f5f0f03f45bad81b97f917c535eb0a Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Tue, 18 Jul 2017 14:10:22 +0800 Subject: [PATCH] Add documentation for Fairing --- Cargo.toml | 2 +- README.md | 9 ++-- examples/fairing.rs | 36 +++++++++++++ src/lib.rs | 122 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 156 insertions(+), 13 deletions(-) create mode 100644 examples/fairing.rs diff --git a/Cargo.toml b/Cargo.toml index 21928f9..0bb6cd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rocket_cors" -version = "0.0.1" +version = "0.1.0" license = "Apache-2.0" authors = ["Yong Wen Chua "] build = "build.rs" diff --git a/README.md b/README.md index b666355..76964a7 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,9 @@ [![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) [![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) -- 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 @@ -27,11 +26,11 @@ might work, but it's not guaranteed. ## Installation - +``` To use the latest `master` branch, for example: diff --git a/examples/fairing.rs b/examples/fairing.rs new file mode 100644 index 0000000..81ebf51 --- /dev/null +++ b/examples/fairing.rs @@ -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(); +} diff --git a/src/lib.rs b/src/lib.rs index 6181ffd..e0d47d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,9 @@ //! [![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) //! [![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) //! -//! - 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 //! @@ -25,11 +24,11 @@ //! //! ## Installation //! -//! +//! rocket_cors = "0.1.0" +//! ``` //! //! To use the latest `master` branch, for example: //! @@ -37,6 +36,114 @@ //! 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. +//! +//! ### `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 requirs 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`. #![allow( legacy_directory_ownership, @@ -367,7 +474,8 @@ impl<'de> Deserialize<'de> for Method { /// 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. /// This struct can also be deserialized by serde.