Skip to content

Commit 401a0ff

Browse files
committed
Add postgres-axum example
1 parent ff8a436 commit 401a0ff

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed

examples/postgres-axum/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "postgres-axum"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
axum = { version = "0.7.5", features = ["json"] }
8+
thiserror = "1.0.60"
9+
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] }
10+
deadpool-postgres = { path = "../../postgres", features = ["serde"] }
11+
tokio-postgres = { version = "0.7.10", features = ["with-uuid-1"] }
12+
dotenvy = "0.15.7"
13+
uuid = { version = "1.8.0", features = ["serde"] }
14+
serde = { version = "1.0.200", features = ["derive"] }
15+
config = "0.14.0"
16+
axum-macros = "0.4.1"

examples/postgres-axum/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# `deadpool-postgres` + `axum` example
2+
3+
This example combines `deadpool-postgres` with a `axum` webservice to
4+
implement a simple API service that responds with JSON read from
5+
PostgreSQL.
6+
7+
## Running the example
8+
9+
The following instructions assumes that your current user can access the
10+
PostgreSQL running at local host passwordless via unix domain socket. The
11+
default installation of PostgreSQL usually already contains the following line
12+
in its [pg_hba.conf](https://www.postgresql.org/docs/16/auth-pg-hba-conf.html):
13+
14+
```txt
15+
local all all peer
16+
```
17+
18+
All you need to do is to create a PostgreSQL user with the same name as
19+
your system user:
20+
21+
```shell
22+
sudo -u postgres createuser -s my_user_name
23+
```
24+
25+
Now create a database
26+
27+
```shell
28+
createdb deadpool
29+
```
30+
31+
Now you should be able to connect to the newly created database without
32+
without any options:
33+
34+
```shell
35+
psql deadpool
36+
```
37+
38+
Load example data
39+
40+
```shell
41+
psql -f fixture.sql deadpool
42+
```
43+
44+
Create `.env` file in this directory
45+
46+
```env
47+
LISTEN=[::1]:8000
48+
PG__DBNAME=deadpool
49+
```
50+
51+
Run the example
52+
53+
```shell
54+
cargo run --release
55+
```
56+
57+
## Configuration options
58+
59+
If you want to connect to your database using a TCP/IP socket you can use
60+
the following template for your `.env` file:
61+
62+
```env
63+
PG__HOST=127.0.0.1
64+
PG__PORT=5432
65+
PG__USER=deadpool
66+
PG__PASSWORD=somepassword
67+
PG__DBNAME=deadpool
68+
```
69+
70+
For more configuration options see `deadpool_postgres::Config`.

examples/postgres-axum/fixture.sql

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public;
2+
3+
CREATE TABLE event (
4+
id uuid DEFAULT public.gen_random_uuid() NOT NULL,
5+
title text NOT NULL
6+
);
7+
8+
COPY event (id, title) FROM stdin;
9+
bec734be-97bd-4f48-b042-5ee859998c56 event1
10+
d36bc40a-fac4-4194-bec4-9ba8c602d994 event2
11+
18012fcf-3c53-4518-b9a6-22479ebe0212 event3
12+
6c4094fc-f8f7-4869-9c57-042bc43f257d event4
13+
e6173a6c-7cf4-4bc5-b676-0871d2705ed6 event5
14+
0d246195-537f-42dd-b7b3-6495116b8f56 event6
15+
c6b452b9-c1f3-4e11-9237-e22e0d6f14bd event7
16+
33ddb912-5bb1-4ba6-a03c-31a087ca8992 event8
17+
0da79dbe-63e9-4a0a-a3cb-34cfc451aa7e event9
18+
dec2f1cd-01af-41ed-a0d9-83a34a1c7b6d event10
19+
ecc1e7e4-828c-4ca3-a8a1-07444bb91300 event11
20+
c6ca56b1-9e02-4381-a248-3b9ef099eb93 event12
21+
f94693f0-789a-4a1f-a218-7399c294f00a event13
22+
c54ee1d7-2f8c-41c5-9478-a01f4c1c0e0b event14
23+
aa213e86-43fe-448d-8862-f2af9c686c82 event15
24+
7135cb1f-00ee-47be-b212-d45a791082ea event16
25+
b7dfa22b-f3a2-4547-a5df-2a6d3f54c90f event17
26+
c339d9fd-ce35-4578-a7c5-908cf619a321 event18
27+
7c49ba99-fdc3-4618-b23b-89ea3e5c4ee4 event19
28+
499b5807-abd2-4c24-9faa-5f463e6a19e3 event20
29+
d2ccbdb5-5b1e-4113-aded-24634ba1fb03 event21
30+
f2c82fc6-5b9a-446a-a6bc-27e814b1521b event22
31+
a818fbed-93dd-4e44-84a8-3591dbff3349 event23
32+
56dd7210-3869-4f1f-9f7a-fc58b3265f63 event24
33+
5803b0e8-98fe-47cd-b61d-478949b2ad70 event25
34+
b4a8d7da-ee5f-4d95-b452-86400697d051 event26
35+
f55fd18a-5532-453c-990e-098df71f2c24 event27
36+
3938cd54-65cf-4638-aba8-5861d9ba729e event28
37+
\.

examples/postgres-axum/src/main.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use axum::{
2+
extract::State,
3+
http::StatusCode,
4+
response::{IntoResponse, Response},
5+
routing::get,
6+
Json, Router,
7+
};
8+
use axum_macros::debug_handler;
9+
use config::ConfigError;
10+
use deadpool_postgres::{Client, Pool, PoolError, Runtime};
11+
use dotenvy::dotenv;
12+
use serde::{Deserialize, Serialize};
13+
use uuid::Uuid;
14+
15+
#[derive(Debug, Deserialize)]
16+
struct Config {
17+
listen: String,
18+
pg: deadpool_postgres::Config,
19+
}
20+
21+
impl Config {
22+
pub fn from_env() -> Result<Self, ConfigError> {
23+
config::Config::builder()
24+
.add_source(config::Environment::default().separator("__"))
25+
.build()
26+
.unwrap()
27+
.try_deserialize()
28+
}
29+
}
30+
31+
#[derive(Deserialize, Serialize)]
32+
struct Event {
33+
id: Uuid,
34+
title: String,
35+
}
36+
37+
#[derive(Debug, thiserror::Error)]
38+
enum Error {
39+
#[error("Pool error: {0}")]
40+
PoolError(#[from] PoolError),
41+
#[error("PostgreSQL error: {0}")]
42+
PgError(#[from] tokio_postgres::Error),
43+
}
44+
45+
impl IntoResponse for Error {
46+
fn into_response(self) -> Response {
47+
(
48+
StatusCode::INTERNAL_SERVER_ERROR,
49+
"An internal error occurred. Please try again later.",
50+
)
51+
.into_response()
52+
}
53+
}
54+
55+
#[debug_handler]
56+
async fn event_list(pool: State<Pool>) -> Result<Json<Vec<Event>>, Error> {
57+
let client: Client = pool.get().await?;
58+
let stmt = client.prepare_cached("SELECT id, title FROM event").await?;
59+
let rows = client.query(&stmt, &[]).await?;
60+
let events = rows
61+
.into_iter()
62+
.map(|row| Event {
63+
id: row.get(0),
64+
title: row.get(1),
65+
})
66+
.collect::<Vec<_>>();
67+
Ok(Json(events))
68+
}
69+
70+
#[tokio::main]
71+
async fn main() {
72+
dotenv().ok();
73+
let config = Config::from_env().unwrap();
74+
let pool = config
75+
.pg
76+
.create_pool(Some(Runtime::Tokio1), tokio_postgres::NoTls)
77+
.unwrap();
78+
let app = Router::new()
79+
.route("/v1.0/event.list", get(event_list))
80+
.with_state(pool);
81+
let listener = tokio::net::TcpListener::bind(&config.listen).await.unwrap();
82+
println!("Server running at http://{}/", &config.listen);
83+
println!(
84+
"Try the following URLs: http://{}/v1.0/event.list",
85+
&config.listen,
86+
);
87+
axum::serve(listener, app).await.unwrap();
88+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy