From aeca0361bd46942b36d05ca09cf9c1229002f905 Mon Sep 17 00:00:00 2001 From: Tyr Chen Date: Sat, 2 Dec 2023 07:52:10 -0800 Subject: [PATCH 1/7] support rustls --- Cargo.toml | 2 ++ README.md | 1 + src/lib.rs | 7 +++++++ 3 files changed, 10 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 7517d85..dd704d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ lz4 = ["dep:lz4", "dep:clickhouse-rs-cityhash-sys"] uuid = ["dep:uuid"] time = ["dep:time"] tls = ["dep:hyper-tls"] +rustls = ["dep:hyper-rustls"] quanta = ["dep:quanta"] [dependencies] @@ -51,6 +52,7 @@ thiserror = "1.0.16" serde = "1.0.106" bytes = "1" tokio = { version = "1.0.1", features = ["rt", "macros"] } +hyper-rustls = { version = "0.24", features = ["http2"], optional = true } hyper = { version = "0.14", features = ["client", "tcp", "http1", "stream"] } hyper-tls = { version = "0.5.0", optional = true } url = "2.1.1" diff --git a/README.md b/README.md index b80ef65..af26faf 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,7 @@ See [examples](https://github.com/loyd/clickhouse.rs/tree/master/examples). ## Feature Flags * `lz4` (enabled by default) — enables `Compression::Lz4` and `Compression::Lz4Hc(_)` variants. If enabled, `Compression::Lz4` is used by default for all queries except for `WATCH`. * `tls` (enabled by default) — supports urls with the `HTTPS` schema. +* `rustls` - enables `rustls` TLS backend. You can use it to avoid OpenSSL dependency. As `tls` is enabled by default, you should disable the `default-features` to use `rustls`. Like this: `clickhouse = { version = "x.y.z", default-features = false, features = ["lz4", "quanta", "rustls"] }` * `quanta` (enabled by default) - uses the [quanta](https://docs.rs/quanta) crate to speed the inserter up. Not used if `test-util` is enabled (thus, time can be managed by `tokio::time::advance()` in custom tests). * `test-util` — adds mocks. See [the example](https://github.com/loyd/clickhouse.rs/tree/master/examples/mock.rs). Use it only in `dev-dependencies`. * `watch` — enables `client.watch` functionality. See the corresponding section for details. diff --git a/src/lib.rs b/src/lib.rs index f767058..ccbb9b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,6 +71,13 @@ impl Default for Client { connector }); + #[cfg(feature = "rustls")] + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_native_roots() + .https_or_http() + .enable_http2() + .wrap_connector(connector); + let client = hyper::Client::builder() .pool_idle_timeout(POOL_IDLE_TIMEOUT) .build(connector); From ad62d75ca1937149d19c10f003c7ec357642fc1f Mon Sep 17 00:00:00 2001 From: Tyr Chen Date: Sun, 3 Dec 2023 09:08:23 -0800 Subject: [PATCH 2/7] cannot reuse connector, otherwise cause a "scheme only can be http" error --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ccbb9b6..c13ebd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ impl Default for Client { .with_native_roots() .https_or_http() .enable_http2() - .wrap_connector(connector); + .build(); let client = hyper::Client::builder() .pool_idle_timeout(POOL_IDLE_TIMEOUT) From 612bd42f7f7ad97472c4acb8694e0744d069373e Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Wed, 31 Jan 2024 10:23:33 -0800 Subject: [PATCH 3/7] Support either rustls or tls (openssl), but not both --- src/lib.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c13ebd0..f8f536a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,6 @@ extern crate static_assertions; use std::{collections::HashMap, sync::Arc, time::Duration}; use hyper::client::connect::HttpConnector; -#[cfg(feature = "tls")] -use hyper_tls::HttpsConnector; pub use clickhouse_derive::Row; @@ -65,18 +63,23 @@ impl Default for Client { // TODO: make configurable in `Client::builder()`. connector.set_keepalive(Some(TCP_KEEPALIVE)); - #[cfg(feature = "tls")] - let connector = HttpsConnector::new_with_connector({ + #[cfg(all(feature = "tls", not(feature = "rustls")))] + let connector = hyper_tls::HttpsConnector::new_with_connector({ connector.enforce_http(false); connector }); - #[cfg(feature = "rustls")] + #[cfg(all(feature = "rustls", not(feature = "tls")))] let connector = hyper_rustls::HttpsConnectorBuilder::new() .with_native_roots() .https_or_http() .enable_http2() - .build(); + .wrap_connector(connector); + + #[cfg(all(feature = "rustls", feature = "tls"))] + compile_error!( + "The rustls and tls features are mutually exclusive and cannot be enabled together" + ); let client = hyper::Client::builder() .pool_idle_timeout(POOL_IDLE_TIMEOUT) From 8e412ef660d6be2ce7f2ab7041c580f6aa17315a Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Tue, 6 Feb 2024 09:27:35 -0800 Subject: [PATCH 4/7] Don't enforce http if any of the TLS features are enabled Otherwise, hyper will error when connecting to an `https` URL: error trying to connect: invalid URL, scheme is not http --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 11423f8..b74f087 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,11 +65,11 @@ impl Default for Client { // TODO: make configurable in `Client::builder()`. connector.set_keepalive(Some(TCP_KEEPALIVE)); + #[cfg(any(feature = "tls", feature = "rustls"))] + connector.enforce_http(false); + #[cfg(all(feature = "tls", not(feature = "rustls")))] - let connector = hyper_tls::HttpsConnector::new_with_connector({ - connector.enforce_http(false); - connector - }); + let connector = hyper_tls::HttpsConnector::new_with_connector(connector); #[cfg(all(feature = "rustls", not(feature = "tls")))] let connector = hyper_rustls::HttpsConnectorBuilder::new() From cf67fb23cdbb2023a5886ea8928c9546c9cf958f Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Mon, 15 Jul 2024 12:04:10 -0700 Subject: [PATCH 5/7] Don't enable `tls` by default, make `rustls` take priority --- Cargo.toml | 4 ++-- README.md | 8 ++++++-- src/lib.rs | 11 +++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e561fd8..cdccff7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ required-features = ["test-util"] debug = true [features] -default = ["lz4", "tls"] +default = ["lz4"] test-util = ["hyper/server"] inserter = ["dep:quanta"] @@ -65,7 +65,7 @@ http-body-util = "0.1.2" hyper = "1.4" hyper-util = { version = "0.1.6", features = ["client-legacy", "http1"] } hyper-tls = { version = "0.6.0", optional = true } -hyper-rustls = { version = "0.27.2", optional = true } +hyper-rustls = { version = "0.27.2", features = ["webpki-roots"], optional = true } url = "2.1.1" futures = "0.3.5" futures-channel = "0.3.30" diff --git a/README.md b/README.md index 525df4e..238436c 100644 --- a/README.md +++ b/README.md @@ -217,14 +217,18 @@ See [examples](https://github.com/loyd/clickhouse.rs/tree/master/examples). ## Feature Flags * `lz4` (enabled by default) — enables `Compression::Lz4` and `Compression::Lz4Hc(_)` variants. If enabled, `Compression::Lz4` is used by default for all queries except for `WATCH`. -* `tls` (enabled by default) — supports urls with the `HTTPS` schema. -* `rustls` - enables `rustls` TLS backend. You can use it to avoid OpenSSL dependency. As `tls` is enabled by default, you should disable the `default-features` to use `rustls`. Like this: `clickhouse = { version = "x.y.z", default-features = false, features = ["lz4", "rustls"] }` +* `tls` — supports urls with the `HTTPS` schema via `hyper-tls`, which links against OpenSSL. +* `rustls` — supports urls with the `HTTPS` schema via `hyper-rustls`, which does not link against OpenSSL. * `inserter` — enables `client.inserter()`. * `test-util` — adds mocks. See [the example](https://github.com/loyd/clickhouse.rs/tree/master/examples/mock.rs). Use it only in `dev-dependencies`. * `watch` — enables `client.watch` functionality. See the corresponding section for details. * `uuid` — adds `serde::uuid` to work with [uuid](https://docs.rs/uuid) crate. * `time` — adds `serde::time` to work with [time](https://docs.rs/time) crate. +> [!NOTE] +> When connecting to ClickHouse via an `HTTPS` url, you must enable either the `tls` or `rustls` features. +> If both are enabled, the `rustls` feature will take precedence. + ## Data Types * `(U)Int(8|16|32|64|128)` maps to/from corresponding `(u|i)(8|16|32|64|128)` types or newtypes around them. * `(U)Int256` aren't supported directly, but there is [a workaround for it](https://github.com/loyd/clickhouse.rs/issues/48). diff --git a/src/lib.rs b/src/lib.rs index 3606252..1151a47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,18 +75,13 @@ impl Default for Client { #[cfg(all(feature = "tls", not(feature = "rustls")))] let connector = hyper_tls::HttpsConnector::new_with_connector(connector); - #[cfg(all(feature = "rustls", not(feature = "tls")))] + #[cfg(feature = "rustls")] let connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_native_roots() + .with_webpki_roots() .https_or_http() - .enable_http2() + .enable_http1() .wrap_connector(connector); - #[cfg(all(feature = "rustls", feature = "tls"))] - compile_error!( - "The rustls and tls features are mutually exclusive and cannot be enabled together" - ); - let client = HyperClient::builder(TokioExecutor::new()) .pool_idle_timeout(POOL_IDLE_TIMEOUT) .build(connector); From aca9894e3fa599dc1b86dd29a8323f9ff630f86c Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Tue, 16 Jul 2024 08:16:17 -0700 Subject: [PATCH 6/7] Rename tls features to mimic reqwest feature naming --- Cargo.toml | 4 ++-- README.md | 8 ++++---- src/lib.rs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cdccff7..6ce08cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,8 +51,8 @@ watch = ["dep:sha-1", "dep:serde_json", "serde/derive"] uuid = ["dep:uuid"] time = ["dep:time"] lz4 = ["dep:lz4", "dep:clickhouse-rs-cityhash-sys"] -tls = ["dep:hyper-tls"] -rustls = ["dep:hyper-rustls"] +native-tls = ["dep:hyper-tls"] +rustls-tls = ["dep:hyper-rustls"] [dependencies] clickhouse-derive = { version = "0.1.1", path = "derive" } diff --git a/README.md b/README.md index 238436c..d07b9bf 100644 --- a/README.md +++ b/README.md @@ -217,8 +217,8 @@ See [examples](https://github.com/loyd/clickhouse.rs/tree/master/examples). ## Feature Flags * `lz4` (enabled by default) — enables `Compression::Lz4` and `Compression::Lz4Hc(_)` variants. If enabled, `Compression::Lz4` is used by default for all queries except for `WATCH`. -* `tls` — supports urls with the `HTTPS` schema via `hyper-tls`, which links against OpenSSL. -* `rustls` — supports urls with the `HTTPS` schema via `hyper-rustls`, which does not link against OpenSSL. +* `native-tls` — supports urls with the `HTTPS` schema via `hyper-tls`, which links against OpenSSL. +* `rustls-tls` — supports urls with the `HTTPS` schema via `hyper-rustls`, which does not link against OpenSSL. * `inserter` — enables `client.inserter()`. * `test-util` — adds mocks. See [the example](https://github.com/loyd/clickhouse.rs/tree/master/examples/mock.rs). Use it only in `dev-dependencies`. * `watch` — enables `client.watch` functionality. See the corresponding section for details. @@ -226,8 +226,8 @@ See [examples](https://github.com/loyd/clickhouse.rs/tree/master/examples). * `time` — adds `serde::time` to work with [time](https://docs.rs/time) crate. > [!NOTE] -> When connecting to ClickHouse via an `HTTPS` url, you must enable either the `tls` or `rustls` features. -> If both are enabled, the `rustls` feature will take precedence. +> When connecting to ClickHouse via an `HTTPS` url, you must enable either the `native-tls` or `rustls-tls` features. +> If both are enabled, the `rustls-tls` feature will take precedence. ## Data Types * `(U)Int(8|16|32|64|128)` maps to/from corresponding `(u|i)(8|16|32|64|128)` types or newtypes around them. diff --git a/src/lib.rs b/src/lib.rs index 1151a47..02e4a5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,13 +69,13 @@ impl Default for Client { // TODO: make configurable in `Client::builder()`. connector.set_keepalive(Some(TCP_KEEPALIVE)); - #[cfg(any(feature = "tls", feature = "rustls"))] + #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] connector.enforce_http(false); - #[cfg(all(feature = "tls", not(feature = "rustls")))] + #[cfg(all(feature = "native-tls", not(feature = "rustls-tls")))] let connector = hyper_tls::HttpsConnector::new_with_connector(connector); - #[cfg(feature = "rustls")] + #[cfg(feature = "rustls-tls")] let connector = hyper_rustls::HttpsConnectorBuilder::new() .with_webpki_roots() .https_or_http() From 55b284711ed75a2eb192d52ad9b8e47766fde657 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Tue, 16 Jul 2024 08:34:37 -0700 Subject: [PATCH 7/7] README: fixup note syntax so it doesn't confuse rustdoc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d07b9bf..479fe45 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ See [examples](https://github.com/loyd/clickhouse.rs/tree/master/examples). * `uuid` — adds `serde::uuid` to work with [uuid](https://docs.rs/uuid) crate. * `time` — adds `serde::time` to work with [time](https://docs.rs/time) crate. -> [!NOTE] +> **NOTE**: > When connecting to ClickHouse via an `HTTPS` url, you must enable either the `native-tls` or `rustls-tls` features. > If both are enabled, the `rustls-tls` feature will take precedence.