diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 209fcae..9654f39 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -26,15 +26,17 @@ jobs:
components: "rustfmt,clippy"
- name: Check code formatting
run: cargo fmt --all -- --check
- - name: Check Clippy lints
- run: cargo clippy --all-targets --all-features -- -D warnings
+ - name: Check Clippy lints (reqwest)
+ run: cargo clippy --all-targets --no-default-features --features use-serde,derive,reqwest-client -- -D warnings
+ - name: Check Clippy lints (surf)
+ run: cargo clippy --all-targets --no-default-features --features use-serde,derive,hyper-client -- -D warnings
compile:
name: Compile (${{ matrix.rust_release }}/${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
- rust_release: [1.45, stable, nightly]
+ rust_release: [1.46, stable, nightly]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
@@ -50,7 +52,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- http-backend: [curl-client, h1-client, h1-client-rustls, hyper-client]
+ http-backend: [curl-client, h1-client, h1-client-rustls, hyper-client, reqwest-client, reqwest-client-rustls]
services:
influxdb:
image: influxdb:1.8
@@ -122,7 +124,7 @@ jobs:
cargo tarpaulin -v \
--target-dir target/tarpaulin \
--workspace \
- --all-features \
+ --features use-serde,derive \
--exclude-files 'derive/*' \
--exclude-files 'target/*' \
--ignore-panics --ignore-tests \
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 920eb58..dcfcc0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- reqwest-based http client (enabled by default)
+
## [0.4.0] - 2021-03-08
### Fixed
diff --git a/README.md b/README.md
index 96b4aa1..908f17d 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,8 @@
-
-
+
+
@@ -62,8 +62,8 @@ use influxdb::{Client, Query, Timestamp};
use influxdb::InfluxDbWriteable;
use chrono::{DateTime, Utc};
-#[async_std::main]
-// or #[tokio::main] if you prefer
+#[tokio::main]
+// or #[async_std::main] if you prefer
async fn main() {
// Connect to db `test` on `http://localhost:8086`
let client = Client::new("http://localhost:8086", "test");
@@ -101,11 +101,21 @@ in the repository.
## Choice of HTTP backend
-To communicate with InfluxDB, you can choose the HTTP backend to be used configuring the appropriate feature:
+To communicate with InfluxDB, you can choose the HTTP backend to be used configuring the appropriate feature. We recommend sticking with the default reqwest-based client, unless you really need async-std compatibility.
-- **[hyper](https://github.com/hyperium/hyper)** (used by default)
+- **[hyper](https://github.com/hyperium/hyper)** (through reqwest, used by default), with [rustls](https://github.com/ctz/rustls)
+ ```toml
+ influxdb = { version = "0.4.0", features = ["derive"] }
+ ```
+
+- **[hyper](https://github.com/hyperium/hyper)** (through reqwest), with native TLS (OpenSSL)
+ ```toml
+ influxdb = { version = "0.4.0", default-features = false, features = ["derive", "use-serde", "reqwest-client"] }
+ ```
+
+- **[hyper](https://github.com/hyperium/hyper)** (through surf), use this if you need tokio 0.2 compatibility
```toml
- influxdb = { version = "0.4.0", features = ["derive"] }
+ influxdb = { version = "0.4.0", default-features = false, features = ["derive", "use-serde", "curl-client"] }
```
- **[curl](https://github.com/alexcrichton/curl-rust)**, using [libcurl](https://curl.se/libcurl/)
```toml
diff --git a/README.tpl b/README.tpl
index 0647cd3..4814b9c 100644
--- a/README.tpl
+++ b/README.tpl
@@ -25,11 +25,11 @@
-
-
+
+
{{readme}}
-@ 2020 Gero Gerke and [contributors](https://github.com/Empty2k12/influxdb-rust/graphs/contributors).
\ No newline at end of file
+@ 2020 Gero Gerke and [contributors](https://github.com/Empty2k12/influxdb-rust/graphs/contributors).
diff --git a/influxdb/Cargo.toml b/influxdb/Cargo.toml
index 6ebbf5a..b493399 100644
--- a/influxdb/Cargo.toml
+++ b/influxdb/Cargo.toml
@@ -18,24 +18,30 @@ travis-ci = { repository = "Empty2k12/influxdb-rust", branch = "master" }
[dependencies]
chrono = { version = "0.4.11", features = ["serde"] }
futures = "0.3.4"
-lazy_static = "1.4.0"
+http = "0.2.4"
influxdb_derive = { version = "0.4.0", optional = true }
+lazy_static = "1.4.0"
regex = "1.3.5"
-surf = { version = "2.2.0", default-features = false }
+reqwest = { version = "0.11.4", default-features = false, optional = true }
+surf = { version = "2.2.0", default-features = false, optional = true }
serde = { version = "1.0.104", features = ["derive"], optional = true }
serde_json = { version = "1.0.48", optional = true }
thiserror = "1.0"
[features]
-use-serde = ["serde", "serde_json"]
-curl-client = ["surf/curl-client"]
-h1-client = ["surf/h1-client"]
-h1-client-rustls = ["surf/h1-client-rustls"]
-hyper-client = ["surf/hyper-client"]
-wasm-client = ["surf/wasm-client"]
-default = ["use-serde", "hyper-client"]
+default = ["use-serde", "reqwest-client-rustls"]
derive = ["influxdb_derive"]
+use-serde = ["serde", "serde_json"]
+
+# http clients
+curl-client = ["surf", "surf/curl-client"]
+h1-client = ["surf", "surf/h1-client"]
+h1-client-rustls = ["surf", "surf/h1-client-rustls"]
+hyper-client = ["surf", "surf/hyper-client"]
+reqwest-client = ["reqwest", "reqwest/native-tls-alpn"]
+reqwest-client-rustls = ["reqwest", "reqwest/rustls-tls-webpki-roots"]
+wasm-client = ["surf", "surf/wasm-client"]
[dev-dependencies]
-async-std = { version = "1.6.5", features = ["attributes"] }
-tokio = { version = "0.2.22", features = ["rt-threaded", "macros"] }
\ No newline at end of file
+async-std = { version = "1.6.5", features = ["attributes", "tokio02", "tokio1"] }
+tokio = { version = "1.7", features = ["macros", "rt-multi-thread"] }
diff --git a/influxdb/src/client/mod.rs b/influxdb/src/client/mod.rs
index 468b0ae..41ac198 100644
--- a/influxdb/src/client/mod.rs
+++ b/influxdb/src/client/mod.rs
@@ -16,7 +16,11 @@
//! ```
use futures::prelude::*;
-use surf::{self, Client as SurfClient, StatusCode};
+use http::StatusCode;
+#[cfg(feature = "reqwest")]
+use reqwest::{Client as HttpClient, Response as HttpResponse};
+#[cfg(feature = "surf")]
+use surf::{Client as HttpClient, Response as HttpResponse};
use crate::query::QueryType;
use crate::Error;
@@ -29,7 +33,7 @@ use std::sync::Arc;
pub struct Client {
pub(crate) url: Arc,
pub(crate) parameters: Arc>,
- pub(crate) client: SurfClient,
+ pub(crate) client: HttpClient,
}
impl Client {
@@ -57,7 +61,7 @@ impl Client {
Client {
url: Arc::new(url.into()),
parameters: Arc::new(parameters),
- client: SurfClient::new(),
+ client: HttpClient::new(),
}
}
@@ -112,10 +116,25 @@ impl Client {
error: format!("{}", err),
})?;
- let build = res.header("X-Influxdb-Build").unwrap().as_str();
- let version = res.header("X-Influxdb-Version").unwrap().as_str();
+ const BUILD_HEADER: &str = "X-Influxdb-Build";
+ const VERSION_HEADER: &str = "X-Influxdb-Version";
- Ok((build.to_owned(), version.to_owned()))
+ #[cfg(feature = "reqwest")]
+ let (build, version) = {
+ let hdrs = res.headers();
+ (
+ hdrs.get(BUILD_HEADER).and_then(|value| value.to_str().ok()),
+ hdrs.get(VERSION_HEADER)
+ .and_then(|value| value.to_str().ok()),
+ )
+ };
+
+ #[cfg(feature = "surf")]
+ let build = res.header(BUILD_HEADER).map(|value| value.as_str());
+ #[cfg(feature = "surf")]
+ let version = res.header(VERSION_HEADER).map(|value| value.as_str());
+
+ Ok((build.unwrap().to_owned(), version.unwrap().to_owned()))
}
/// Sends a [`ReadQuery`](crate::ReadQuery) or [`WriteQuery`](crate::WriteQuery) to the InfluxDB Server.
@@ -184,32 +203,31 @@ impl Client {
self.client.post(url).body(query.get()).query(¶meters)
}
- }
- .map_err(|err| Error::UrlConstructionError {
+ };
+
+ #[cfg(feature = "surf")]
+ let request_builder = request_builder.map_err(|err| Error::UrlConstructionError {
error: err.to_string(),
})?;
- let request = request_builder.build();
- let mut res = self
- .client
- .send(request)
+ let res = request_builder
+ .send()
.map_err(|err| Error::ConnectionError {
error: err.to_string(),
})
.await?;
+ check_status(&res)?;
- match res.status() {
- StatusCode::Unauthorized => return Err(Error::AuthorizationError),
- StatusCode::Forbidden => return Err(Error::AuthenticationError),
- _ => {}
- }
+ #[cfg(feature = "reqwest")]
+ let body = res.text();
+ #[cfg(feature = "surf")]
+ let mut res = res;
+ #[cfg(feature = "surf")]
+ let body = res.body_string();
- let s = res
- .body_string()
- .await
- .map_err(|_| Error::DeserializationError {
- error: "response could not be converted to UTF-8".to_string(),
- })?;
+ let s = body.await.map_err(|_| Error::DeserializationError {
+ error: "response could not be converted to UTF-8".to_string(),
+ })?;
// todo: improve error parsing without serde
if s.contains("\"error\"") {
@@ -222,6 +240,17 @@ impl Client {
}
}
+pub(crate) fn check_status(res: &HttpResponse) -> Result<(), Error> {
+ let status = res.status();
+ if status == StatusCode::UNAUTHORIZED.as_u16() {
+ Err(Error::AuthorizationError)
+ } else if status == StatusCode::FORBIDDEN.as_u16() {
+ Err(Error::AuthenticationError)
+ } else {
+ Ok(())
+ }
+}
+
#[cfg(test)]
mod tests {
use super::Client;
diff --git a/influxdb/src/integrations/serde_integration/mod.rs b/influxdb/src/integrations/serde_integration/mod.rs
index 3a734af..e0b6508 100644
--- a/influxdb/src/integrations/serde_integration/mod.rs
+++ b/influxdb/src/integrations/serde_integration/mod.rs
@@ -48,11 +48,9 @@
mod de;
-use surf::StatusCode;
-
use serde::{de::DeserializeOwned, Deserialize};
-use crate::{Client, Error, Query, ReadQuery};
+use crate::{client::check_status, Client, Error, Query, ReadQuery};
#[derive(Deserialize)]
#[doc(hidden)]
@@ -143,30 +141,29 @@ impl Client {
let url = &format!("{}/query", &self.url);
let mut parameters = self.parameters.as_ref().clone();
parameters.insert("q", read_query);
- let request = self
- .client
- .get(url)
- .query(¶meters)
- .map_err(|err| Error::UrlConstructionError {
- error: err.to_string(),
- })?
- .build();
+ let request_builder = self.client.get(url).query(¶meters);
+
+ #[cfg(feature = "surf")]
+ let request_builder = request_builder.map_err(|err| Error::UrlConstructionError {
+ error: err.to_string(),
+ })?;
- let mut res = self
- .client
- .send(request)
+ let res = request_builder
+ .send()
.await
.map_err(|err| Error::ConnectionError {
error: err.to_string(),
})?;
+ check_status(&res)?;
- match res.status() {
- StatusCode::Unauthorized => return Err(Error::AuthorizationError),
- StatusCode::Forbidden => return Err(Error::AuthenticationError),
- _ => {}
- }
+ #[cfg(feature = "reqwest")]
+ let body = res.bytes();
+ #[cfg(feature = "surf")]
+ let mut res = res;
+ #[cfg(feature = "surf")]
+ let body = res.body_bytes();
- let body = res.body_bytes().await.map_err(|err| Error::ProtocolError {
+ let body = body.await.map_err(|err| Error::ProtocolError {
error: err.to_string(),
})?;
diff --git a/influxdb/src/lib.rs b/influxdb/src/lib.rs
index 117f07f..bfd207d 100644
--- a/influxdb/src/lib.rs
+++ b/influxdb/src/lib.rs
@@ -30,8 +30,8 @@
//! use influxdb::InfluxDbWriteable;
//! use chrono::{DateTime, Utc};
//!
-//! #[async_std::main]
-//! // or #[tokio::main] if you prefer
+//! #[tokio::main]
+//! // or #[async_std::main] if you prefer
//! async fn main() {
//! // Connect to db `test` on `http://localhost:8086`
//! let client = Client::new("http://localhost:8086", "test");
@@ -69,11 +69,21 @@
//!
//! # Choice of HTTP backend
//!
-//! To communicate with InfluxDB, you can choose the HTTP backend to be used configuring the appropriate feature:
+//! To communicate with InfluxDB, you can choose the HTTP backend to be used configuring the appropriate feature. We recommend sticking with the default reqwest-based client, unless you really need async-std compatibility.
//!
-//! - **[hyper](https://github.com/hyperium/hyper)** (used by default)
+//! - **[hyper](https://github.com/hyperium/hyper)** (through reqwest, used by default), with [rustls](https://github.com/ctz/rustls)
+//! ```toml
+//! influxdb = { version = "0.4.0", features = ["derive"] }
+//! ```
+//!
+//! - **[hyper](https://github.com/hyperium/hyper)** (through reqwest), with native TLS (OpenSSL)
+//! ```toml
+//! influxdb = { version = "0.4.0", default-features = false, features = ["derive", "use-serde", "reqwest-client"] }
+//! ```
+//!
+//! - **[hyper](https://github.com/hyperium/hyper)** (through surf), use this if you need tokio 0.2 compatibility
//! ```toml
-//! influxdb = { version = "0.4.0", features = ["derive"] }
+//! influxdb = { version = "0.4.0", default-features = false, features = ["derive", "use-serde", "curl-client"] }
//! ```
//! - **[curl](https://github.com/alexcrichton/curl-rust)**, using [libcurl](https://curl.se/libcurl/)
//! ```toml
@@ -99,6 +109,12 @@
#![allow(clippy::needless_doctest_main)]
#![allow(clippy::needless_lifetimes)] // False positive in client/mod.rs query fn
+#[cfg(all(feature = "reqwest", feature = "surf"))]
+compile_error!("You need to choose between reqwest and surf; enabling both is not supported");
+
+#[cfg(not(any(feature = "reqwest", feature = "surf")))]
+compile_error!("You need to choose an http client; consider not disabling default features");
+
mod client;
mod error;
mod query;
diff --git a/influxdb/tests/integration_tests.rs b/influxdb/tests/integration_tests.rs
index d92f405..631023b 100644
--- a/influxdb/tests/integration_tests.rs
+++ b/influxdb/tests/integration_tests.rs
@@ -28,9 +28,9 @@ async fn test_ping_influx_db_async_std() {
/// INTEGRATION TEST
///
-/// This test case tests whether the InfluxDB server can be connected to and gathers info about it * tested with tokio
+/// This test case tests whether the InfluxDB server can be connected to and gathers info about it - tested with tokio 1.0
#[tokio::test]
-#[cfg(not(tarpaulin_include))]
+#[cfg(not(any(tarpaulin_include, feature = "hyper-client")))]
async fn test_ping_influx_db_tokio() {
let client = create_client("notusedhere");
let result = client.ping().await;
@@ -386,7 +386,7 @@ async fn test_json_query() {
/// INTEGRATION TEST
///
/// This test case tests whether the response to a GROUP BY can be parsed by
-// deserialize_next_tagged into a tags struct
+/// deserialize_next_tagged into a tags struct
#[async_std::test]
#[cfg(feature = "use-serde")]
#[cfg(not(tarpaulin_include))]
@@ -453,8 +453,10 @@ async fn test_json_query_tagged() {
/// is equal to the data which was written to the database
/// (tested with tokio)
#[tokio::test]
-#[cfg(feature = "use-serde")]
-#[cfg(not(tarpaulin_include))]
+#[cfg(all(
+ feature = "use-serde",
+ not(any(tarpaulin_include, feature = "hyper-client"))
+))]
async fn test_json_query_vec() {
use serde::Deserialize;