Gate serde behind a feature flag (#25)

* Gate serde behind a feature flag

Fixes #16

* Fix travis build configuration
This commit is contained in:
Yong Wen Chua 2017-09-05 14:11:28 +08:00 committed by GitHub
parent 1ac3bedc96
commit 715913a6b3
6 changed files with 121 additions and 61 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
target/ target/
**/*.rs.bk **/*.rs.bk
Cargo.lock Cargo.lock
**/*.rs.fmt

View File

@ -2,6 +2,13 @@ sudo: false
language: rust language: rust
rust: rust:
- nightly-2017-09-05 - nightly-2017-09-05
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: dig1qv7Qc4IrAKoszmetgU1qyMnd5bPZC+jpgKaiimDX5mGiJJB3qHWql6+jeR5JDEcFGKE8/oFMkCtg78E6Gv6FcJ6qwB3Ks4MRfZlLmTPcwPj0pf6789M9FRnTsPMp3HHmeoVsfM4ujZYgk3Az+bDU4En6/8U4RCdl0CAmRGwMt9QtKzSygiHivCs/BpqkQ+Coq0HezaYDzBrNF3Q0gsxgy+5DALwSaQqAsKatb73w7i4EuyzrgfPW8OvkUj3i2Zc2zuY8FCElZY1H7igQK4P/EFyKyiRbyTzVsvwbqBwPPQuVzT8wwmOqcCmQACnuLD9EiF0iP2sAtWTJ0H2HosptVqxQbqmsvGHLzAza1jb1buLBgeIvPwDRP1sQmxVRgD1JkzRiZkt8EwN6MYzqtmfPA32Aukoji47n1zmyombJlAKkC8gKSXc6XTByOXcFNcYQ0BbyT9Tngn9K+YZUmSG/Wf33GKOCQc80I07FnOOsfYUpU43Vjv7xuFdyJn9vS9nxZzhZURQzrfJg4mgcqOTRGHIFGHdvrnVzDJX60gWQMoRadLjLoknGH86BUScmEJ0dWwhHS8dBeYboTNJuiW2EQtcnvDawQ8F79bhyNLVhM2ICoaf9Rok/lMjLUEN+6HzOGzw/rQYtJaJ6trF5CFwZIf3q2kHbW6wybwU/KTg=
matrix:
- CARGO_FLAGS="--all-features"
- CARGO_FLAGS="--no-default-features"
addons: addons:
apt: apt:
packages: packages:
@ -14,12 +21,8 @@ before_script:
export PATH=$HOME/.local/bin:$PATH export PATH=$HOME/.local/bin:$PATH
script: script:
- | - |
travis-cargo build -- --all-features --all && travis-cargo build -- "${CARGO_FLAGS}" &&
travis-cargo test -- --all-features --all && travis-cargo test -- "${CARGO_FLAGS}" &&
travis-cargo --only nightly-2017-09-05 doc -- --no-deps --all-features --all travis-cargo --only nightly-2017-09-05 doc -- --no-deps "${CARGO_FLAGS}"
after_success: after_success:
- travis-cargo --only nightly-2017-09-05 doc-upload - test $CARGO_FLAGS = "--all-features" && travis-cargo --only nightly-2017-09-05 doc-upload
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- secure: dig1qv7Qc4IrAKoszmetgU1qyMnd5bPZC+jpgKaiimDX5mGiJJB3qHWql6+jeR5JDEcFGKE8/oFMkCtg78E6Gv6FcJ6qwB3Ks4MRfZlLmTPcwPj0pf6789M9FRnTsPMp3HHmeoVsfM4ujZYgk3Az+bDU4En6/8U4RCdl0CAmRGwMt9QtKzSygiHivCs/BpqkQ+Coq0HezaYDzBrNF3Q0gsxgy+5DALwSaQqAsKatb73w7i4EuyzrgfPW8OvkUj3i2Zc2zuY8FCElZY1H7igQK4P/EFyKyiRbyTzVsvwbqBwPPQuVzT8wwmOqcCmQACnuLD9EiF0iP2sAtWTJ0H2HosptVqxQbqmsvGHLzAza1jb1buLBgeIvPwDRP1sQmxVRgD1JkzRiZkt8EwN6MYzqtmfPA32Aukoji47n1zmyombJlAKkC8gKSXc6XTByOXcFNcYQ0BbyT9Tngn9K+YZUmSG/Wf33GKOCQc80I07FnOOsfYUpU43Vjv7xuFdyJn9vS9nxZzhZURQzrfJg4mgcqOTRGHIFGHdvrnVzDJX60gWQMoRadLjLoknGH86BUScmEJ0dWwhHS8dBeYboTNJuiW2EQtcnvDawQ8F79bhyNLVhM2ICoaf9Rok/lMjLUEN+6HzOGzw/rQYtJaJ6trF5CFwZIf3q2kHbW6wybwU/KTg=

View File

@ -14,15 +14,23 @@ categories = ["web-programming"]
[badges] [badges]
travis-ci = { repository = "lawliet89/rocket_cors" } travis-ci = { repository = "lawliet89/rocket_cors" }
[features]
default = ["serialization"]
# Serialization and deserialization support for settings
serialization = ["serde", "serde_derive", "unicase_serde", "url_serde"]
[dependencies] [dependencies]
log = "0.3" log = "0.3"
rocket = "0.3" rocket = "0.3"
serde = "1.0"
serde_derive = "1.0"
unicase = "2.0" unicase = "2.0"
unicase_serde = "0.1.0"
url = "1.5.1" url = "1.5.1"
url_serde = "0.2.0"
# Optional dependencies that are activated by the various features
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
unicase_serde = { version = "0.1.0", optional = true }
url_serde = { version = "0.2.0", optional = true }
[build-dependencies] [build-dependencies]
ansi_term = "0.9" ansi_term = "0.9"
@ -33,3 +41,10 @@ hyper = "0.10"
rocket_codegen = "0.3" rocket_codegen = "0.3"
serde_json = "1.0" serde_json = "1.0"
serde_test = "1.0" serde_test = "1.0"
[[example]]
name = "json"
required-features = ["serialization"]
[package.metadata.docs.rs]
all-features = true

View File

@ -1,4 +1,6 @@
//! This example is to demonstrate the JSON serialization and deserialization of the Cors settings //! This example is to demonstrate the JSON serialization and deserialization of the Cors settings
//!
//! Note: This requires the `serialization` feature which is enabled by default.
extern crate rocket; extern crate rocket;
extern crate rocket_cors as cors; extern crate rocket_cors as cors;
extern crate serde_json; extern crate serde_json;

View File

@ -9,14 +9,18 @@ use rocket::{self, Outcome};
use rocket::http::Status; use rocket::http::Status;
use rocket::request::{self, FromRequest}; use rocket::request::{self, FromRequest};
use unicase::UniCase; use unicase::UniCase;
use unicase_serde;
use url; use url;
#[cfg(feature = "serialization")]
use unicase_serde;
#[cfg(feature = "serialization")]
use url_serde; use url_serde;
/// A case insensitive header name /// A case insensitive header name
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug, Hash)] #[derive(Eq, PartialEq, Clone, Debug, Hash)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct HeaderFieldName( pub struct HeaderFieldName(
#[serde(with = "unicase_serde::unicase")] #[cfg_attr(feature = "serialization", serde(with = "unicase_serde::unicase"))]
UniCase<String> UniCase<String>
); );
@ -58,9 +62,10 @@ impl FromStr for HeaderFieldName {
pub type HeaderFieldNamesSet = HashSet<HeaderFieldName>; pub type HeaderFieldNamesSet = HashSet<HeaderFieldName>;
/// A wrapped `url::Url` to allow for deserialization /// A wrapped `url::Url` to allow for deserialization
#[derive(Eq, PartialEq, Clone, Hash, Debug, Serialize, Deserialize)] #[derive(Eq, PartialEq, Clone, Hash, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Url( pub struct Url(
#[serde(with = "url_serde")] #[cfg_attr(feature = "serialization", serde(with = "url_serde"))]
url::Url url::Url
); );

View File

@ -36,6 +36,16 @@
//! rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" } //! 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 `Cors` struct that is described below. If you would like to disable this, simply change
//! your `Cargo.toml` to:
//!
//! ```toml
//! rocket_cors = { version = "0.2.0", default-features = false }
//! ```
//!
//! ## Usage //! ## Usage
//! //!
//! Before you can add CORS responses to your application, you need to create a `Cors` struct that //! Before you can add CORS responses to your application, you need to create a `Cors` struct that
@ -52,7 +62,8 @@
//! The [`Cors` struct](struct.Cors.html) contains the settings for CORS requests to be validated //! 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 //! 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 //! are documented on the [`Cors` struct](struct.Cors.html) page. You can also deserialize
//! the struct from some format like JSON, YAML or TOML. //! the struct from some format like JSON, YAML or TOML when the default `serialization` feature
//! is enabled.
//! //!
//! ### Three modes of operation //! ### Three modes of operation
//! //!
@ -437,18 +448,25 @@
extern crate log; extern crate log;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
extern crate unicase;
extern crate url;
#[cfg(feature = "serialization")]
extern crate serde; extern crate serde;
#[cfg(feature = "serialization")]
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate unicase; #[cfg(feature = "serialization")]
extern crate unicase_serde; extern crate unicase_serde;
extern crate url; #[cfg(feature = "serialization")]
extern crate url_serde; extern crate url_serde;
#[cfg(test)] #[cfg(test)]
extern crate hyper; extern crate hyper;
#[cfg(feature = "serialization")]
#[cfg(test)] #[cfg(test)]
extern crate serde_test; extern crate serde_test;
#[cfg(feature = "serialization")]
#[cfg(test)] #[cfg(test)]
extern crate serde_json; extern crate serde_json;
@ -471,7 +489,6 @@ use rocket::{Outcome, State};
use rocket::http::{self, Status}; use rocket::http::{self, Status};
use rocket::request::{Request, FromRequest}; use rocket::request::{Request, FromRequest};
use rocket::response; use rocket::response;
use serde::{Serialize, Deserialize};
use headers::{HeaderFieldName, HeaderFieldNamesSet, Origin, AccessControlRequestHeaders, use headers::{HeaderFieldName, HeaderFieldNamesSet, Origin, AccessControlRequestHeaders,
AccessControlRequestMethod, Url}; AccessControlRequestMethod, Url};
@ -599,7 +616,8 @@ impl<'r> response::Responder<'r> for Error {
/// ///
/// This enum is serialized and deserialized /// This enum is serialized and deserialized
/// ["Externally tagged"](https://serde.rs/enum-representations.html) /// ["Externally tagged"](https://serde.rs/enum-representations.html)
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum AllOrSome<T> { pub enum AllOrSome<T> {
/// Everything is allowed. Usually equivalent to the "*" value. /// Everything is allowed. Usually equivalent to the "*" value.
All, All,
@ -672,16 +690,25 @@ impl fmt::Display for Method {
} }
} }
impl Serialize for Method { #[cfg(feature = "serialization")]
mod method_serde {
use std::fmt;
use std::str::FromStr;
use serde::{self, Serialize, Deserialize};
use Method;
impl Serialize for Method {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: serde::Serializer, S: serde::Serializer,
{ {
serializer.serialize_str(self.as_str()) serializer.serialize_str(self.as_str())
} }
} }
impl<'de> Deserialize<'de> for Method { impl<'de> Deserialize<'de> for Method {
fn deserialize<D>(deserializer: D) -> Result<Method, D::Error> fn deserialize<D>(deserializer: D) -> Result<Method, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
@ -709,6 +736,7 @@ impl<'de> Deserialize<'de> for Method {
deserializer.deserialize_string(MethodVisitor) deserializer.deserialize_string(MethodVisitor)
} }
}
} }
/// A list of allowed origins. Either Some origins are allowed, or all origins are allowed. /// A list of allowed origins. Either Some origins are allowed, or all origins are allowed.
@ -796,7 +824,8 @@ impl AllowedHeaders {
/// documentation at the [crate root](index.html) for usage information. /// 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 with the `serialization` feature which is
/// enabled by default.
/// ///
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) is implemented for this /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) is implemented for this
/// struct. The default for each field is described in the docuementation for the field. /// struct. The default for each field is described in the docuementation for the field.
@ -864,7 +893,8 @@ impl AllowedHeaders {
/// } /// }
/// ///
/// ``` /// ```
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)] #[derive(Eq, PartialEq, Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Cors { pub struct Cors {
/// Origins that are allowed to make requests. /// Origins that are allowed to make requests.
/// Will be verified against the `Origin` request header. /// Will be verified against the `Origin` request header.
@ -882,7 +912,7 @@ pub struct Cors {
/// Defaults to `All`. /// Defaults to `All`.
/// ///
/// ``` /// ```
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub allowed_origins: AllowedOrigins, pub allowed_origins: AllowedOrigins,
/// The list of methods which the allowed origins are allowed to access for /// The list of methods which the allowed origins are allowed to access for
/// non-simple requests. /// non-simple requests.
@ -891,7 +921,7 @@ pub struct Cors {
/// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model). /// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model).
/// ///
/// Defaults to `[GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE]` /// Defaults to `[GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE]`
#[serde(default = "Cors::default_allowed_methods")] #[cfg_attr(feature = "serialization", serde(default = "Cors::default_allowed_methods"))]
pub allowed_methods: AllowedMethods, pub allowed_methods: AllowedMethods,
/// The list of header field names which can be used when this resource is accessed by allowed /// The list of header field names which can be used when this resource is accessed by allowed
/// origins. /// origins.
@ -903,7 +933,7 @@ pub struct Cors {
/// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model). /// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model).
/// ///
/// Defaults to `All`. /// Defaults to `All`.
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub allowed_headers: AllOrSome<HashSet<HeaderFieldName>>, pub allowed_headers: AllOrSome<HashSet<HeaderFieldName>>,
/// Allows users to make authenticated requests. /// Allows users to make authenticated requests.
/// If true, injects the `Access-Control-Allow-Credentials` header in responses. /// If true, injects the `Access-Control-Allow-Credentials` header in responses.
@ -914,7 +944,7 @@ pub struct Cors {
/// in an `Error::CredentialsWithWildcardOrigin` error during Rocket launch or runtime. /// in an `Error::CredentialsWithWildcardOrigin` error during Rocket launch or runtime.
/// ///
/// Defaults to `false`. /// Defaults to `false`.
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub allow_credentials: bool, pub allow_credentials: bool,
/// The list of headers which are safe to expose to the API of a CORS API specification. /// The list of headers which are safe to expose to the API of a CORS API specification.
/// This corresponds to the `Access-Control-Expose-Headers` responde header. /// This corresponds to the `Access-Control-Expose-Headers` responde header.
@ -923,13 +953,13 @@ pub struct Cors {
/// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model). /// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model).
/// ///
/// This defaults to an empty set. /// This defaults to an empty set.
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub expose_headers: HashSet<String>, pub expose_headers: HashSet<String>,
/// The maximum time for which this CORS request maybe cached. This value is set as the /// The maximum time for which this CORS request maybe cached. This value is set as the
/// `Access-Control-Max-Age` header. /// `Access-Control-Max-Age` header.
/// ///
/// This defaults to `None` (unset). /// This defaults to `None` (unset).
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub max_age: Option<usize>, pub max_age: Option<usize>,
/// If true, and the `allowed_origins` parameter is `All`, a wildcard /// If true, and the `allowed_origins` parameter is `All`, a wildcard
/// `Access-Control-Allow-Origin` response header is sent, rather than the requests /// `Access-Control-Allow-Origin` response header is sent, rather than the requests
@ -943,14 +973,14 @@ pub struct Cors {
/// in an `Error::CredentialsWithWildcardOrigin` error during Rocket launch or runtime. /// in an `Error::CredentialsWithWildcardOrigin` error during Rocket launch or runtime.
/// ///
/// Defaults to `false`. /// Defaults to `false`.
#[serde(default)] #[cfg_attr(feature = "serialization", serde(default))]
pub send_wildcard: bool, pub send_wildcard: bool,
/// When used as Fairing, Cors will need to redirect failed CORS checks to a custom route to /// When used as Fairing, Cors will need to redirect failed CORS checks to a custom route to
/// be mounted by the fairing. Specify the base the route so that it doesn't clash with any /// be mounted by the fairing. Specify the base the route so that it doesn't clash with any
/// of your existing routes. /// of your existing routes.
/// ///
/// Defaults to "/cors" /// Defaults to "/cors"
#[serde(default = "Cors::default_fairing_route_base")] #[cfg_attr(feature = "serialization", serde(default = "Cors::default_fairing_route_base"))]
pub fairing_route_base: String, pub fairing_route_base: String,
} }
@ -1753,6 +1783,7 @@ mod tests {
use rocket::local::Client; use rocket::local::Client;
use rocket::http::Header; use rocket::http::Header;
#[cfg(feature = "serialization")]
use serde_json; use serde_json;
use super::*; use super::*;
@ -1808,6 +1839,7 @@ mod tests {
} }
/// Check that the the default deserialization matches the one returned by `Default::default` /// Check that the the default deserialization matches the one returned by `Default::default`
#[cfg(feature = "serialization")]
#[test] #[test]
fn cors_default_deserialization_is_correct() { fn cors_default_deserialization_is_correct() {
let deserialized: Cors = serde_json::from_str("{}").expect("To not fail"); let deserialized: Cors = serde_json::from_str("{}").expect("To not fail");
@ -2039,11 +2071,13 @@ mod tests {
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
struct MethodTest { struct MethodTest {
method: ::Method, method: ::Method,
} }
#[cfg(feature = "serialization")]
#[test] #[test]
fn method_serde_roundtrip() { fn method_serde_roundtrip() {
use serde_test::{Token, assert_tokens}; use serde_test::{Token, assert_tokens};