Skip to content

Commit 92e1506

Browse files
Luuk Westerweiznich
Luuk Wester
authored andcommitted
Add an example of using a pooled bb8 connection with rustls
1 parent 3e220ce commit 92e1506

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
/target
1+
**/target
22
Cargo.lock
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "pooled-pg-with-rustls"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
diesel = { version = "2.0.3", default-features = false, features = ["postgres"] }
10+
diesel-async = { version = "0.2.0", features = ["bb8", "postgres"] }
11+
futures-util = "0.3.21"
12+
rustls = "0.20.8"
13+
rustls-native-certs = "0.6.2"
14+
tokio = { version = "1.2.0", default-features = false, features = ["macros", "rt-multi-thread"] }
15+
tokio-postgres = "0.7.7"
16+
tokio-postgres-rustls = "0.9.0"
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use diesel::{ConnectionError, ConnectionResult};
2+
use diesel_async::pooled_connection::bb8::Pool;
3+
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
4+
use diesel_async::AsyncPgConnection;
5+
use futures_util::future::BoxFuture;
6+
use futures_util::FutureExt;
7+
use std::time::Duration;
8+
9+
#[tokio::main]
10+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
11+
let db_url = std::env::var("DATABASE_URL").expect("Env var `DATABASE_URL` not set");
12+
13+
// First we have to construct a connection manager with our custom `establish_connection`
14+
// function
15+
let mgr = AsyncDieselConnectionManager::<AsyncPgConnection>::new_with_setup(
16+
db_url,
17+
establish_connection,
18+
);
19+
// From that connection we can then create a pool, here given with some example settings.
20+
let pool = Pool::builder()
21+
.max_size(10)
22+
.min_idle(Some(5))
23+
.max_lifetime(Some(Duration::from_secs(60 * 60 * 24)))
24+
.idle_timeout(Some(Duration::from_secs(60 * 2)))
25+
.build(mgr)
26+
.await?;
27+
28+
// Now we can use our pool to run queries over a TLS-secured connection:
29+
let conn = pool.get().await?;
30+
let _ = conn;
31+
32+
Ok(())
33+
}
34+
35+
fn establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> {
36+
let fut = async {
37+
let rustls_config = rustls::ClientConfig::builder()
38+
.with_safe_defaults()
39+
.with_root_certificates(root_certs())
40+
.with_no_client_auth();
41+
let tls = tokio_postgres_rustls::MakeRustlsConnect::new(rustls_config);
42+
let (client, conn) = tokio_postgres::connect(config, tls)
43+
.await
44+
.map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
45+
tokio::spawn(async move {
46+
if let Err(e) = conn.await {
47+
eprintln!("Database connection: {e}");
48+
}
49+
});
50+
AsyncPgConnection::try_from(client).await
51+
};
52+
fut.boxed()
53+
}
54+
55+
fn root_certs() -> rustls::RootCertStore {
56+
let mut roots = rustls::RootCertStore::empty();
57+
let certs = rustls_native_certs::load_native_certs().expect("Certs not loadable!");
58+
let certs: Vec<_> = certs.into_iter().map(|cert| cert.0).collect();
59+
roots.add_parsable_certificates(&certs);
60+
roots
61+
}

0 commit comments

Comments
 (0)