Skip to content

Commit

Permalink
Merge pull request #85 from cognitedata/rbt/reqwest
Browse files Browse the repository at this point in the history
Update HTTP client support
  • Loading branch information
rbtcollins authored May 13, 2024
2 parents cdee650 + 1ad1e33 commit 02cbb09
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 21 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/ci-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- surf-client
# no need for reqwest-client-rustls, it changes only internals of reqwest
- reqwest-client
- reqwest-client-11

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -58,13 +59,13 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: build
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls,reqwest-client-11,reqwest-client-11-rustls --all-targets

- uses: actions-rs/cargo@v1
# We test with approximately all-features to ensure that that does build (excludes nightly only backtrace)
with:
command: test
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls,reqwest-client-11,reqwest-client-11-rustls --all-targets

- uses: actions-rs/cargo@v1
with:
Expand All @@ -74,14 +75,14 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls --all-targets -- -D warnings
args: --features strict,surf-client,reqwest-client,reqwest-client-rustls,reqwest-client-11,reqwest-client-11-rustls --all-targets -- -D warnings

msrv:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- 1.59.0 # MSRV
- 1.60.0 # MSRV

steps:
- uses: actions/checkout@v2
Expand Down
26 changes: 18 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ license = "Apache-2.0"
name = "unleash-api-client"
readme = "README.md"
repository = "https://github.com/cognitedata/unleash-client-rust/"
rust-version = "1.59"
version = "0.10.3"
rust-version = "1.60"
version = "0.11.0"

[badges]
[badges.maintenance]
Expand All @@ -20,12 +20,16 @@ status = "experimental"
[features]
# Enable backtrace feature in anyhow
backtrace = ["anyhow/backtrace"]
default = ["surf-client"]
# Force clients to make a choice about which client to use
default = []
# Enable the functional test suite
functional = []
reqwest-client = ["reqwest", "reqwest/default-tls"]
# Built in HTTP clients
reqwest-client = ["reqwest", "reqwest?/default-tls"]
reqwest-client-11 = ["reqwest-11", "reqwest-11?/default-tls"]
# For users that don't want to depend on OpenSSL.
reqwest-client-rustls = ["reqwest", "reqwest/rustls-tls"]
reqwest-client-11-rustls = ["reqwest-11", "reqwest-11?/rustls-tls"]
reqwest-client-rustls = ["reqwest", "reqwest?/rustls-tls"]
# To error if an unsupported API feature is present
strict = []
# For use with --no-default-features
Expand All @@ -39,7 +43,7 @@ name = "is_enabled"
bench = false
name = "dump-features"
path = "src/bin/dump-features.rs"
required-features = ["async-std", "surf-client"]
required-features = ["surf-client"]

[dependencies]
anyhow = "1.0.44"
Expand Down Expand Up @@ -68,14 +72,20 @@ version = "0.4.19"
default-features = false
features = ["json"]
optional = true
version = "0.11.10"
version = "0.12"

[dependencies.reqwest-11]
default-features = false
features = ["json"]
optional = true
package = "reqwest"
version = "0.11"

[dependencies.serde]
features = ["derive"]
version = "1.0"

[dev-dependencies]
# async-std = "1.10.0"
criterion = "0.3.5" # Remember to update audit.toml
futures = "0.3.17"
maplit = "1.0.2"
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ surf or reqwest support is built in, or any async HTTP client can be provided by
the user if they implement the thin trait used to abstract over the actual
client.

Examples with async-std and tokio are in the examples/ in the source
tree.
Examples with async-std (feature 'surf-client') and tokio (feature
'reqwest-client') are in the examples/ in the source tree. See the API docs for
more feature information.

To use it in a sync program, run an async executor and `block_on()` the relevant
calls. As the client specification requires sending background metrics to the
Expand Down Expand Up @@ -69,7 +70,7 @@ enable_string_features | N/A | By default the Rust SDK requires you to define an

## Status

Core Unleash API features work, with Rust 1.59 or above. The MSRV for this project is weakly enforced: when a hard dependency raises its version, so will the minimum version tested against, but if older rust versions work for a user, that is not prevented. `time` in particular is known to enforce a 6-month compiler age, so regular increases with the minimum version tested against are expected.
Core Unleash API features work, with Rust 1.60 or above. The MSRV for this project is weakly enforced: when a hard dependency raises its version, so will the minimum version tested against, but if older rust versions work for a user, that is not prevented. `time` in particular is known to enforce a 6-month compiler age, so regular increases with the minimum version tested against are expected.

Unimplemented Unleash specified features:

Expand Down
4 changes: 4 additions & 0 deletions benches/is_enabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ fn batch(c: &mut Criterion) {
use surf::Client as HttpClient;
} else if #[cfg(feature = "reqwest")] {
use reqwest::Client as HttpClient;
} else if #[cfg(feature = "reqwest-11")] {
use reqwest_11::Client as HttpClient;
} else {
compile_error!("Cannot run test suite without a client enabled");
}
Expand Down Expand Up @@ -423,6 +425,8 @@ fn single_call(c: &mut Criterion) {
use surf::Client as HttpClient;
} else if #[cfg(feature = "reqwest")] {
use reqwest::Client as HttpClient;
} else if #[cfg(feature = "reqwest-11")] {
use reqwest_11::Client as HttpClient;
} else {
compile_error!("Cannot run test suite without a client enabled");
}
Expand Down
4 changes: 4 additions & 0 deletions examples/threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
use reqwest::Client as HttpClient;
use tokio::runtime::Runtime;
let rt = Arc::new(Runtime::new().unwrap());
} else if #[cfg(feature = "reqwest-11")] {
use reqwest_11::Client as HttpClient;
use tokio::runtime::Runtime;
let rt = Arc::new(Runtime::new().unwrap());
} else {
compile_error!("Cannot run test suite without a client enabled");
}
Expand Down
2 changes: 2 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,8 @@ mod tests {
use surf::Client as HttpClient;
} else if #[cfg(feature = "reqwest")] {
use reqwest::Client as HttpClient;
} else if #[cfg(feature = "reqwest-11")] {
use reqwest_11::Client as HttpClient;
} else {
compile_error!("Cannot run test suite without a client enabled");
}
Expand Down
2 changes: 2 additions & 0 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#[cfg(feature = "reqwest")]
mod reqwest;
#[cfg(feature = "reqwest-11")]
mod reqwest_11;
mod shim;
#[cfg(feature = "surf")]
mod surf;
Expand Down
48 changes: 48 additions & 0 deletions src/http/reqwest_11.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Shim reqwest into an unleash HTTP client

// Copyright 2022 Cognite AS

use async_trait::async_trait;
use serde::{de::DeserializeOwned, Serialize};

use super::HttpClient;

#[async_trait]
impl HttpClient for reqwest_11::Client {
type HeaderName = reqwest_11::header::HeaderName;
type Error = reqwest_11::Error;
type RequestBuilder = reqwest_11::RequestBuilder;

fn build_header(name: &'static str) -> Result<Self::HeaderName, Self::Error> {
Ok(Self::HeaderName::from_static(name))
}

fn get(&self, uri: &str) -> Self::RequestBuilder {
self.get(uri)
}

fn post(&self, uri: &str) -> Self::RequestBuilder {
self.post(uri)
}

fn header(
builder: Self::RequestBuilder,
key: &Self::HeaderName,
value: &str,
) -> Self::RequestBuilder {
builder.header(key.clone(), value)
}

async fn get_json<T: DeserializeOwned>(req: Self::RequestBuilder) -> Result<T, Self::Error> {
req.send().await?.json::<T>().await
}

async fn post_json<T: Serialize + Sync>(
req: Self::RequestBuilder,
content: &T,
) -> Result<bool, Self::Error> {
let req = req.json(content);
let res = req.send().await?;
Ok(res.status().is_success())
}
}
10 changes: 8 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ strategy memoization function.
```no_run
# mod i {
# cfg_if::cfg_if!{
# if #[cfg(not(feature = "surf"))] {
# if #[cfg(not(feature = "surf-client"))] {
# pub fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
# Ok(())
# }
Expand Down Expand Up @@ -99,13 +99,17 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
* **backtrace** -
Enable backtrace feature in anyhow (nightly only)
* **default** -
The default feature enables the async-std/surf feature.
By default no features are enabled.
* **functional** -
Only relevant to developers: enables the functional test suite.
* **reqwest-client** -
Enables reqwest with OpenSSL TLS support
* **reqwest-client-11** -
Enables reqwest 0.11 with OpenSSL TLS support
* **reqwest-client-rustls** -
Enables reqwest with RusTLS support
* **reqwest-client-11-rustls** -
Enables reqwest 0.11 with RusTLS support
* **strict** -
Turn unexpected fields in API responses into errors
* **surf-client** -
Expand Down Expand Up @@ -159,6 +163,8 @@ pub mod prelude {
pub use surf::Client as DefaultClient;
} else if #[cfg(feature = "reqwest")] {
pub use reqwest::Client as DefaultClient;
} else if #[cfg(feature = "reqwest-11")] {
pub use reqwest_11::Client as DefaultClient;
}
}
}
4 changes: 3 additions & 1 deletion tests/clientspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ mod tests {
}
_ => false,
},
None => other.payload.get("type").is_none() && other.payload.get("value").is_none(),
None => !other.payload.contains_key("type") && !other.payload.contains_key("value"),
};
self.enabled == other.enabled && self._name == other.name && payload_matches
}
Expand Down Expand Up @@ -92,6 +92,8 @@ mod tests {
use surf::Client as HttpClient;
} else if #[cfg(feature = "reqwest")] {
use reqwest::Client as HttpClient;
} else if #[cfg(feature = "reqwest-11")] {
use reqwest_11::Client as HttpClient;
} else {
compile_error!("Cannot run test suite without a client enabled");
}
Expand Down
18 changes: 15 additions & 3 deletions tests/functional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ mod tests {
}
}

#[cfg(feature = "reqwest")]
#[cfg(or(feature = "reqwest", feature = "reqwest-11"))]
struct TokioJoinHandle {
inner: tokio::task::JoinHandle<()>,
}
Expand All @@ -80,9 +80,9 @@ mod tests {
}
}

#[cfg(feature = "reqwest")]
#[cfg(or(feature = "reqwest", feature = "reqwest-11"))]
struct TokioAsync;
#[cfg(feature = "reqwest")]
#[cfg(or(feature = "reqwest", feature = "reqwest-11"))]
#[async_trait]
impl AsyncImpl for TokioAsync {
type JoinHandle = TokioJoinHandle;
Expand Down Expand Up @@ -142,6 +142,11 @@ mod tests {
async fn test_smoke_async_reqwest() {
test_smoke_async::<reqwest::Client>().await.unwrap();
}
#[cfg(feature = "reqwest-11")]
#[tokio::test]
async fn test_smoke_async_reqwest() {
test_smoke_async::<reqwest_11::Client>().await.unwrap();
}

async fn test_smoke_threaded<C, A>(
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>>
Expand Down Expand Up @@ -204,4 +209,11 @@ mod tests {
.await
.unwrap();
}
#[cfg(feature = "reqwest-11")]
#[tokio::test]
async fn test_smoke_threaded_reqwest() {
test_smoke_threaded::<reqwest_11::Client, TokioAsync>()
.await
.unwrap();
}
}

0 comments on commit 02cbb09

Please sign in to comment.