diff --git a/Cargo.lock b/Cargo.lock
index fb147bfe40..2031a91d41 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -113,6 +113,17 @@ dependencies = [
"url",
]
+[[package]]
+name = "async-rustls"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c238bd34d425674d8003b8d674cc04baf74e1b71802f3c62451e3bf86f2858ef"
+dependencies = [
+ "futures-lite 1.11.1",
+ "rustls",
+ "webpki",
+]
+
[[package]]
name = "async-std"
version = "1.6.2"
@@ -251,9 +262,9 @@ checksum = "d2468ff7bf85066b4a3678fede6fe66db31846d753ff0adfbfab2c6a6e81612b"
dependencies = [
"async-channel",
"atomic-waker",
- "futures-lite",
+ "futures-lite 0.1.9",
"once_cell",
- "parking",
+ "parking 1.0.6",
"waker-fn",
]
@@ -676,9 +687,12 @@ checksum = "829694371bd7bbc6aee17c4ff624aad8bf9f4dc06c6f9f6071eaa08c89530d10"
[[package]]
name = "fastrand"
-version = "1.3.3"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36a9cb09840f81cd211e435d00a4e487edd263dc3c8ff815c32dd76ad668ebed"
+checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
+dependencies = [
+ "instant",
+]
[[package]]
name = "fnv"
@@ -775,7 +789,22 @@ dependencies = [
"futures-core",
"futures-io",
"memchr",
- "parking",
+ "parking 1.0.6",
+ "pin-project-lite",
+ "waker-fn",
+]
+
+[[package]]
+name = "futures-lite"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "381a7ad57b1bad34693f63f6f377e1abded7a9c85c9d3eb6771e11c60aaadab9"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking 2.0.0",
"pin-project-lite",
"waker-fn",
]
@@ -1373,6 +1402,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c"
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
[[package]]
name = "parking_lot"
version = "0.11.0"
@@ -1687,6 +1722,21 @@ dependencies = [
"winapi 0.3.9",
]
+[[package]]
+name = "ring"
+version = "0.16.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi 0.3.9",
+]
+
[[package]]
name = "rsa"
version = "0.3.0"
@@ -1728,6 +1778,19 @@ dependencies = [
"semver",
]
+[[package]]
+name = "rustls"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
+dependencies = [
+ "base64 0.12.3",
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
[[package]]
name = "ryu"
version = "1.0.5"
@@ -1765,6 +1828,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+[[package]]
+name = "sct"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
[[package]]
name = "security-framework"
version = "0.4.4"
@@ -2077,6 +2150,7 @@ dependencies = [
"time 0.2.16",
"url",
"uuid",
+ "webpki",
"whoami",
]
@@ -2153,10 +2227,12 @@ dependencies = [
"actix-rt",
"actix-threadpool",
"async-native-tls",
+ "async-rustls",
"async-std",
"once_cell",
"tokio",
"tokio-native-tls",
+ "tokio-rustls",
]
[[package]]
@@ -2522,6 +2598,18 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-rustls"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a"
+dependencies = [
+ "futures-core",
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
[[package]]
name = "toml"
version = "0.5.6"
@@ -2587,6 +2675,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
[[package]]
name = "url"
version = "2.1.1"
@@ -2721,6 +2815,16 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "webpki"
+version = "0.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
[[package]]
name = "wepoll-sys-stjepang"
version = "1.0.6"
diff --git a/Cargo.toml b/Cargo.toml
index 8d2705f5c9..89801991d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -63,6 +63,10 @@ runtime-actix-native-tls = [ "sqlx-core/runtime-actix-native-tls", "sqlx-macros/
runtime-async-std-native-tls = [ "sqlx-core/runtime-async-std-native-tls", "sqlx-macros/runtime-async-std-native-tls", "_rt-async-std" ]
runtime-tokio-native-tls = [ "sqlx-core/runtime-tokio-native-tls", "sqlx-macros/runtime-tokio-native-tls", "_rt-tokio" ]
+runtime-actix-rustls = [ "sqlx-core/runtime-actix-rustls", "sqlx-macros/runtime-actix-rustls", "_rt-actix" ]
+runtime-async-std-rustls = [ "sqlx-core/runtime-async-std-rustls", "sqlx-macros/runtime-async-std-rustls", "_rt-async-std" ]
+runtime-tokio-rustls = [ "sqlx-core/runtime-tokio-rustls", "sqlx-macros/runtime-tokio-rustls", "_rt-tokio" ]
+
# for conditional compilation
_rt-actix = []
_rt-async-std = []
diff --git a/README.md b/README.md
index 7d09992743..833559d1dc 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@ SQLx is an async, pure Rust† SQL crate featuring compile-time check
* **Pure Rust**. The Postgres and MySQL/MariaDB drivers are written in pure Rust using **zero** unsafe†† code.
- * **Runtime Agnostic**. Works on different runtimes ([async-std](https://crates.io/crates/async-std) / [tokio](https://crates.io/crates/tokio) / [actix](https://crates.io/crates/actix-rt)).
+ * **Runtime Agnostic**. Works on different runtimes ([async-std](https://crates.io/crates/async-std) / [tokio](https://crates.io/crates/tokio) / [actix](https://crates.io/crates/actix-rt)) and TLS backends ([native-tls](https://crates.io/crates/native-tls), [rustls](https://crates.io/crates/rustls)).
† The SQLite driver uses the libsqlite3 C library as SQLite is an embedded database (the only way
we could be pure Rust for SQLite is by porting _all_ of SQLite to Rust).
@@ -109,12 +109,14 @@ SQLx is compatible with the [`async-std`], [`tokio`] and [`actix`] runtimes.
[`tokio`]: https://github.com/tokio-rs/tokio
[`actix`]: https://github.com/actix/actix-net
-By default, you get `async-std`. If you want a different runtime or TLS backend, just disable the default features and activate the corresponding feature, for example for tokio:
+You can also select between [`native-tls`] and [`rustls`] for the TLS backend.
+
+By default, you get `async-std` + `native-tls`. If you want a different runtime or TLS backend, just disable the default features and activate the corresponding feature, for example for tokio + rustls:
```toml
# Cargo.toml
[dependencies]
-sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "runtime-tokio-native-tls", "macros" ] }
+sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "runtime-tokio-rustls", "macros" ] }
```
The runtime and TLS backend not being separate feature sets to select is a workaround for a [Cargo issue](https://github.com/rust-lang/cargo/issues/3494).
@@ -123,10 +125,16 @@ sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "runti
* `runtime-async-std-native-tls` (on by default): Use the `async-std` runtime and `native-tls` TLS backend.
+ * `runtime-async-std-rustls`: Use the `async-std` runtime and `rustls` TLS backend.
+
* `runtime-tokio-native-tls`: Use the `tokio` runtime and `native-tls` TLS backend.
+ * `runtime-tokio-rustls`: Use the `tokio` runtime and `rustls` TLS backend.
+
* `runtime-actix-native-tls`: Use the `actix` runtime and `native-tls` TLS backend.
+ * `runtime-actix-rustls`: Use the `actix` runtime and `rustls` TLS backend.
+
* `postgres`: Add support for the Postgres database server.
* `mysql`: Add support for the MySQL (and MariaDB) database server.
diff --git a/sqlx-bench/Cargo.toml b/sqlx-bench/Cargo.toml
index ea945a114a..9e3f123327 100644
--- a/sqlx-bench/Cargo.toml
+++ b/sqlx-bench/Cargo.toml
@@ -10,6 +10,10 @@ runtime-actix-native-tls = [ "sqlx/runtime-actix-native-tls", "sqlx-rt/runtime-a
runtime-async-std-native-tls = [ "sqlx/runtime-async-std-native-tls", "sqlx-rt/runtime-async-std-native-tls" ]
runtime-tokio-native-tls = [ "sqlx/runtime-tokio-native-tls", "sqlx-rt/runtime-tokio-native-tls" ]
+runtime-actix-rustls = [ "sqlx/runtime-actix-rustls", "sqlx-rt/runtime-actix-rustls" ]
+runtime-async-std-rustls = [ "sqlx/runtime-async-std-rustls", "sqlx-rt/runtime-async-std-rustls" ]
+runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls", "sqlx-rt/runtime-tokio-rustls" ]
+
postgres = ["sqlx/postgres"]
[dependencies]
diff --git a/sqlx-bench/README.md b/sqlx-bench/README.md
index c769eb5be9..ca21933631 100644
--- a/sqlx-bench/README.md
+++ b/sqlx-bench/README.md
@@ -24,7 +24,7 @@ You must choose a runtime to execute the benchmarks on; the feature flags are th
```bash
cargo bench --features runtime-tokio-native-tls
-cargo bench --features runtime-async-std-native-tls
+cargo bench --features runtime-async-std-rustls
```
When complete, the benchmark results will be in `target/criterion/`.
diff --git a/sqlx-core/Cargo.toml b/sqlx-core/Cargo.toml
index f4db49fa7a..dc52d18fe1 100644
--- a/sqlx-core/Cargo.toml
+++ b/sqlx-core/Cargo.toml
@@ -34,14 +34,20 @@ decimal = [ "rust_decimal", "num-bigint" ]
json = [ "serde", "serde_json" ]
# runtimes
-runtime-actix-native-tls = [ "sqlx-rt/runtime-actix-native-tls", "_rt-actix" ]
-runtime-async-std-native-tls = [ "sqlx-rt/runtime-async-std-native-tls", "_rt-async-std" ]
-runtime-tokio-native-tls = [ "sqlx-rt/runtime-tokio-native-tls", "_rt-tokio" ]
+runtime-actix-native-tls = [ "sqlx-rt/runtime-actix-native-tls", "_tls-native-tls", "_rt-actix" ]
+runtime-async-std-native-tls = [ "sqlx-rt/runtime-async-std-native-tls", "_tls-native-tls", "_rt-async-std" ]
+runtime-tokio-native-tls = [ "sqlx-rt/runtime-tokio-native-tls", "_tls-native-tls", "_rt-tokio" ]
+
+runtime-actix-rustls = [ "sqlx-rt/runtime-actix-rustls", "_tls-rustls", "_rt-actix" ]
+runtime-async-std-rustls = [ "sqlx-rt/runtime-async-std-rustls", "_tls-rustls", "_rt-async-std" ]
+runtime-tokio-rustls = [ "sqlx-rt/runtime-tokio-rustls", "_tls-rustls", "_rt-tokio" ]
# for conditional compilation
_rt-actix = []
_rt-async-std = []
_rt-tokio = []
+_tls-native-tls = []
+_tls-rustls = [ "webpki" ]
# support offline/decoupled building (enables serialization of `Describe`)
offline = [ "serde", "either/serde" ]
@@ -98,3 +104,4 @@ uuid = { version = "0.8.1", default-features = false, optional = true, features
whoami = "0.9.0"
stringprep = "0.1.2"
lru-cache = "0.1.2"
+webpki = { version = "0.21.3", optional = true }
diff --git a/sqlx-core/src/error.rs b/sqlx-core/src/error.rs
index ff9b05edd2..5d1022529c 100644
--- a/sqlx-core/src/error.rs
+++ b/sqlx-core/src/error.rs
@@ -240,6 +240,14 @@ impl From for Error {
}
}
+#[cfg(feature = "_tls-rustls")]
+impl From for Error {
+ #[inline]
+ fn from(error: webpki::InvalidDNSNameError) -> Self {
+ Error::Tls(Box::new(error))
+ }
+}
+
// Format an error message as a `Protocol` error
macro_rules! err_protocol {
($expr:expr) => {
diff --git a/sqlx-core/src/net/tls.rs b/sqlx-core/src/net/tls.rs
index 89c1b91d31..27549449c7 100644
--- a/sqlx-core/src/net/tls.rs
+++ b/sqlx-core/src/net/tls.rs
@@ -44,6 +44,9 @@ where
}
};
+ #[cfg(feature = "_tls-rustls")]
+ let host = webpki::DNSNameRef::try_from_ascii_str(host)?;
+
*self = MaybeTlsStream::Tls(
connector
.connect(host, stream)
@@ -166,12 +169,15 @@ where
match self {
MaybeTlsStream::Raw(s) => s,
- #[cfg(not(feature = "_rt-async-std"))]
- MaybeTlsStream::Tls(s) => s.get_ref().get_ref().get_ref(),
+ #[cfg(feature = "_tls-rustls")]
+ MaybeTlsStream::Tls(s) => s.get_ref().0,
- #[cfg(feature = "_rt-async-std")]
+ #[cfg(all(feature = "_rt-async-std", feature = "_tls-native-tls"))]
MaybeTlsStream::Tls(s) => s.get_ref(),
+ #[cfg(all(not(feature = "_rt-async-std"), feature = "_tls-native-tls"))]
+ MaybeTlsStream::Tls(s) => s.get_ref().get_ref().get_ref(),
+
MaybeTlsStream::Upgrading => panic!(io::Error::from(io::ErrorKind::ConnectionAborted)),
}
}
@@ -185,12 +191,15 @@ where
match self {
MaybeTlsStream::Raw(s) => s,
- #[cfg(not(feature = "_rt-async-std"))]
- MaybeTlsStream::Tls(s) => s.get_mut().get_mut().get_mut(),
+ #[cfg(feature = "_tls-rustls")]
+ MaybeTlsStream::Tls(s) => s.get_mut().0,
- #[cfg(feature = "_rt-async-std")]
+ #[cfg(all(feature = "_rt-async-std", feature = "_tls-native-tls"))]
MaybeTlsStream::Tls(s) => s.get_mut(),
+ #[cfg(all(not(feature = "_rt-async-std"), feature = "_tls-native-tls"))]
+ MaybeTlsStream::Tls(s) => s.get_mut().get_mut().get_mut(),
+
MaybeTlsStream::Upgrading => panic!(io::Error::from(io::ErrorKind::ConnectionAborted)),
}
}
diff --git a/sqlx-macros/Cargo.toml b/sqlx-macros/Cargo.toml
index e2578bf854..e713eac1da 100644
--- a/sqlx-macros/Cargo.toml
+++ b/sqlx-macros/Cargo.toml
@@ -24,6 +24,10 @@ runtime-actix-native-tls = [ "sqlx-core/runtime-actix-native-tls", "sqlx-rt/runt
runtime-async-std-native-tls = [ "sqlx-core/runtime-async-std-native-tls", "sqlx-rt/runtime-async-std-native-tls", "_rt-async-std" ]
runtime-tokio-native-tls = [ "sqlx-core/runtime-tokio-native-tls", "sqlx-rt/runtime-tokio-native-tls", "_rt-tokio" ]
+runtime-actix-rustls = [ "sqlx-core/runtime-actix-rustls", "sqlx-rt/runtime-actix-rustls", "_rt-actix" ]
+runtime-async-std-rustls = [ "sqlx-core/runtime-async-std-rustls", "sqlx-rt/runtime-async-std-rustls", "_rt-async-std" ]
+runtime-tokio-rustls = [ "sqlx-core/runtime-tokio-rustls", "sqlx-rt/runtime-tokio-rustls", "_rt-tokio" ]
+
# for conditional compilation
_rt-actix = []
_rt-async-std = []
diff --git a/sqlx-rt/Cargo.toml b/sqlx-rt/Cargo.toml
index 43434c9f59..cab3ba258c 100644
--- a/sqlx-rt/Cargo.toml
+++ b/sqlx-rt/Cargo.toml
@@ -15,17 +15,24 @@ runtime-actix-native-tls = [ "_rt-actix", "_tls-native-tls", "tokio-native-tls"
runtime-async-std-native-tls = [ "_rt-async-std", "_tls-native-tls", "async-native-tls" ]
runtime-tokio-native-tls = [ "_rt-tokio", "_tls-native-tls", "tokio-native-tls" ]
+runtime-actix-rustls = [ "_rt-actix", "_tls-rustls", "tokio-rustls" ]
+runtime-async-std-rustls = [ "_rt-async-std", "_tls-rustls", "async-rustls" ]
+runtime-tokio-rustls = [ "_rt-tokio", "_tls-rustls", "tokio-rustls" ]
+
# Not used directly and not re-exported from sqlx
_rt-actix = [ "actix-rt", "actix-threadpool", "tokio", "once_cell" ]
_rt-async-std = [ "async-std" ]
_rt-tokio = [ "tokio", "once_cell" ]
_tls-native-tls = [ ]
+_tls-rustls = [ ]
[dependencies]
async-native-tls = { version = "0.3.3", optional = true }
+async-rustls = { version = "0.1.0", optional = true }
actix-rt = { version = "1.1.1", optional = true }
actix-threadpool = { version = "0.3.2", optional = true }
async-std = { version = "1.6.0", features = [ "unstable" ], optional = true }
tokio = { version = "0.2.21", optional = true, features = [ "blocking", "stream", "fs", "tcp", "uds", "macros", "rt-core", "rt-threaded", "time", "dns", "io-util" ] }
tokio-native-tls = { version = "0.1.0", optional = true }
+tokio-rustls = { version = "0.14.0", optional = true }
once_cell = { version = "1.4", features = ["std"], optional = true }
diff --git a/sqlx-rt/src/lib.rs b/sqlx-rt/src/lib.rs
index 83d99e7789..0bc47eb64e 100644
--- a/sqlx-rt/src/lib.rs
+++ b/sqlx-rt/src/lib.rs
@@ -2,20 +2,26 @@
feature = "runtime-actix-native-tls",
feature = "runtime-async-std-native-tls",
feature = "runtime-tokio-native-tls",
+ feature = "runtime-actix-rustls",
+ feature = "runtime-async-std-rustls",
+ feature = "runtime-tokio-rustls",
)))]
compile_error!(
"one of the features ['runtime-actix-native-tls', 'runtime-async-std-native-tls', \
- 'runtime-tokio-native-tls'] must be enabled"
+ 'runtime-tokio-native-tls', 'runtime-actix-rustls', 'runtime-async-std-rustls', \
+ 'runtime-tokio-rustls'] must be enabled"
);
#[cfg(any(
all(feature = "_rt-actix", feature = "_rt-async-std"),
all(feature = "_rt-actix", feature = "_rt-tokio"),
all(feature = "_rt-async-std", feature = "_rt-tokio"),
+ all(feature = "_tls-native-tls", feature = "_tls-rustls"),
))]
compile_error!(
"only one of ['runtime-actix-native-tls', 'runtime-async-std-native-tls', \
- 'runtime-tokio-native-tls'] can be enabled"
+ 'runtime-tokio-native-tls', 'runtime-actix-rustls', 'runtime-async-std-rustls', \
+ 'runtime-tokio-rustls'] can be enabled"
);
//
@@ -75,10 +81,17 @@ mod tokio_runtime {
#[cfg(all(
feature = "_tls-native-tls",
any(feature = "_rt-tokio", feature = "_rt-actix"),
- not(feature = "_rt-async-std"),
+ not(any(feature = "_tls-rustls", feature = "_rt-async-std")),
))]
pub use tokio_native_tls::{TlsConnector, TlsStream};
+#[cfg(all(
+ feature = "_tls-rustls",
+ any(feature = "_rt-tokio", feature = "_rt-actix"),
+ not(any(feature = "_tls-native-tls", feature = "_rt-async-std")),
+))]
+pub use tokio_rustls::{client::TlsStream, TlsConnector};
+
//
// tokio
//
@@ -167,3 +180,14 @@ where
#[cfg(all(feature = "async-native-tls", not(feature = "tokio-native-tls")))]
pub use async_native_tls::{TlsConnector, TlsStream};
+
+#[cfg(all(
+ feature = "_tls-rustls",
+ feature = "_rt-async-std",
+ not(any(
+ feature = "_tls-native-tls",
+ feature = "_rt-tokio",
+ feature = "_rt-actix"
+ )),
+))]
+pub use async_rustls::{client::TlsStream, TlsConnector};
diff --git a/src/lib.rs b/src/lib.rs
index 0808435610..e2a404b074 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,8 +7,8 @@
))]
compile_error!(
"the features 'runtime-actix', 'runtime-async-std' and 'runtime-tokio' have been removed in
- favor of new features 'runtime-{rt}-{tls}' where rt is one of 'actix', 'async-std' and
- 'tokio'."
+ favor of new features 'runtime-{rt}-{tls}' where rt is one of 'actix', 'async-std' and 'tokio'
+ and 'tls' is one of 'native-tls' and 'rustls'."
);
pub use sqlx_core::acquire::Acquire;