From a70b8a95994b85ce73830196d94aa243a148c9d4 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Fri, 24 Jun 2022 22:25:23 +0200 Subject: [PATCH 1/2] Allow developers/users to opt into strict parsing This is primarily useful for developing new versions of the API client - we can do a strict build where the Unleash client specification is expected to have nothing unparsable. Some users may wish to prevent silent failures when they upgrade and use new features though, so this could be useful there too. --- Cargo.toml | 2 ++ client-specification | 2 +- src/api.rs | 14 +++++++------- src/context.rs | 2 +- src/lib.rs | 2 ++ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 605cf90..853b22a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ functional = [] reqwest-client = ["reqwest", "reqwest/default-tls"] # For users that don't want to depend on OpenSSL. reqwest-client-rustls = ["reqwest", "reqwest/rustls-tls"] +# To error if an unsupported API feature is present +strict = [] # For use with --no-default-features surf-client = ["surf", "async-std"] diff --git a/client-specification b/client-specification index 3d91a8f..d069632 160000 --- a/client-specification +++ b/client-specification @@ -1 +1 @@ -Subproject commit 3d91a8f18e1679994d308e5dde47954ae2def56d +Subproject commit d0696320bb8999acaaaa4b29291ee85e6172d736 diff --git a/src/api.rs b/src/api.rs index 79fbc0c..261a4fa 100644 --- a/src/api.rs +++ b/src/api.rs @@ -7,7 +7,7 @@ use chrono::Utc; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Features { pub version: u8, pub features: Vec, @@ -20,7 +20,7 @@ impl Features { } #[derive(Clone, Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Feature { pub name: String, #[serde(default)] @@ -33,7 +33,7 @@ pub struct Feature { } #[derive(Clone, Default, Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Strategy { pub constraints: Option>, pub name: String, @@ -41,7 +41,7 @@ pub struct Strategy { } #[derive(Clone, Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Constraint { #[serde(rename = "contextName")] pub context_name: String, @@ -51,7 +51,7 @@ pub struct Constraint { #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(tag = "operator", content = "values")] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub enum ConstraintExpression { #[serde(rename = "IN")] In(Vec), @@ -60,7 +60,7 @@ pub enum ConstraintExpression { } #[derive(Clone, Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Variant { pub name: String, pub weight: u8, @@ -69,7 +69,7 @@ pub struct Variant { } #[derive(Clone, Serialize, Deserialize, Debug)] -// #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct VariantOverride { #[serde(rename = "contextName")] pub context_name: String, diff --git a/src/context.rs b/src/context.rs index eb8ff54..89ad438 100644 --- a/src/context.rs +++ b/src/context.rs @@ -26,7 +26,7 @@ impl<'de> de::Deserialize<'de> for IPAddress { } #[derive(Debug, Default, Deserialize)] -#[serde(deny_unknown_fields)] +#[cfg_attr(feature = "strict", serde(deny_unknown_fields))] pub struct Context { #[serde(rename = "userId")] pub user_id: Option, diff --git a/src/lib.rs b/src/lib.rs index 6335911..cf99657 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,8 @@ fn main() -> Result<(), Box> { Enables reqwest with OpenSSL TLS support * **reqwest-client-rustls** - Enables reqwest with RusTLS support +* **strict** - + Turn unexpected fields in API responses into errors * **surf-client** - Enables Surf as the HTTP client to retrieve flags */ From e73dae16b02eb0169ed2d5d6cf25f436311ee246 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Fri, 24 Jun 2022 22:28:34 +0200 Subject: [PATCH 2/2] Run CI tests in strict mode This will prevent silent merging of API conformance updates that don't actually implement everything. --- .github/workflows/ci-matrix.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-matrix.yml b/.github/workflows/ci-matrix.yml index 8516d99..8de7d9f 100644 --- a/.github/workflows/ci-matrix.yml +++ b/.github/workflows/ci-matrix.yml @@ -30,12 +30,12 @@ jobs: - uses: actions-rs/cargo@v1 with: command: build - args: --no-default-features --features ${{ matrix.features }} + args: --no-default-features --features strict,${{ matrix.features }} - uses: actions-rs/cargo@v1 with: command: test - args: --no-default-features --features ${{ matrix.features }} + args: --no-default-features --features strict,${{ matrix.features }} clippy: runs-on: ubuntu-latest @@ -59,13 +59,13 @@ jobs: - uses: actions-rs/cargo@v1 with: command: build - args: --features surf-client,reqwest-client,reqwest-client-rustls --all-targets + args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets - uses: actions-rs/cargo@v1 - # We test with all-features to ensure that that does build + # We test with approximately all-features to ensure that that does build (excludes nightly only backtrace) with: command: test - args: --features surf-client,reqwest-client,reqwest-client-rustls --all-targets + args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets - uses: actions-rs/cargo@v1 with: @@ -75,4 +75,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: clippy - args: --features surf-client,reqwest-client,reqwest-client-rustls --all-targets -- -D warnings + args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets -- -D warnings