got nested routing working

This commit is contained in:
2024-12-10 03:04:55 -08:00
parent 5e04815911
commit 6ce6b9289a
10 changed files with 328 additions and 19 deletions

237
Cargo.lock generated
View File

@@ -44,6 +44,21 @@ version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.92"
@@ -56,6 +71,8 @@ version = "0.1.0"
dependencies = [
"anyhow",
"axum",
"chrono",
"dotenv",
"serde",
"serde_json",
"sqlx",
@@ -64,6 +81,7 @@ dependencies = [
"utoipa",
"utoipa-axum",
"utoipa-swagger-ui",
"uuid",
]
[[package]]
@@ -234,6 +252,20 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.6",
]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@@ -249,6 +281,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
version = "0.2.14"
@@ -352,6 +390,12 @@ dependencies = [
"syn",
]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "dotenvy"
version = "0.15.7"
@@ -697,6 +741,29 @@ dependencies = [
"tower-service",
]
[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.5.0"
@@ -724,6 +791,16 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -1105,6 +1182,21 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "ring"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rsa"
version = "0.9.6"
@@ -1178,6 +1270,46 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rustls"
version = "0.23.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
dependencies = [
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]]
name = "rustls-webpki"
version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.18"
@@ -1391,6 +1523,7 @@ dependencies = [
"atoi",
"byteorder",
"bytes",
"chrono",
"crc",
"crossbeam-queue",
"either",
@@ -1409,14 +1542,19 @@ dependencies = [
"once_cell",
"paste",
"percent-encoding",
"rustls",
"rustls-pemfile",
"serde",
"serde_json",
"sha2",
"smallvec",
"sqlformat",
"thiserror",
"tokio",
"tokio-stream",
"tracing",
"url",
"webpki-roots",
]
[[package]]
@@ -1454,6 +1592,7 @@ dependencies = [
"sqlx-sqlite",
"syn",
"tempfile",
"tokio",
"url",
]
@@ -1468,6 +1607,7 @@ dependencies = [
"bitflags",
"byteorder",
"bytes",
"chrono",
"crc",
"digest",
"dotenvy",
@@ -1509,6 +1649,7 @@ dependencies = [
"base64",
"bitflags",
"byteorder",
"chrono",
"crc",
"dotenvy",
"etcetera",
@@ -1544,6 +1685,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680"
dependencies = [
"atoi",
"chrono",
"flume",
"futures-channel",
"futures-core",
@@ -1677,6 +1819,17 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-stream"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tower"
version = "0.5.1"
@@ -1782,6 +1935,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.2"
@@ -1847,6 +2006,12 @@ dependencies = [
"zip",
]
[[package]]
name = "uuid"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
[[package]]
name = "vcpkg"
version = "0.2.15"
@@ -1881,6 +2046,69 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
[[package]]
name = "webpki-roots"
version = "0.26.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "whoami"
version = "1.5.2"
@@ -1900,6 +2128,15 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.48.0"

View File

@@ -13,4 +13,12 @@ utoipa-axum = "0.1.2"
serde = "1"
serde_json = "1"
anyhow = "1.0.92"
sqlx = "0.8.2"
sqlx = { version = "0.8.2", features = [
"postgres",
"chrono",
"runtime-tokio-rustls",
"macros",
] }
uuid = "1.11.0"
chrono = "0.4.39"
dotenv = "0.15.0"

View File

@@ -9,7 +9,7 @@ services:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
volumes:
- ./postgres-data:/var/lib/postgresql/data
- ~/databases/uplifting-api-postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:

11
src/db.rs Normal file
View File

@@ -0,0 +1,11 @@
use anyhow::{Context, Result};
use sqlx::postgres::PgPoolOptions;
pub async fn db() -> Result<sqlx::Pool<sqlx::Postgres>> {
let db_url = std::env::var("DATABASE_URL").context("DATABASE_URL must be set")?;
Ok(PgPoolOptions::new()
.max_connections(5)
.connect(&db_url)
.await?)
}

View File

@@ -1,23 +1,30 @@
use std::net::Ipv4Addr;
use std::{net::Ipv4Addr, sync::Arc};
use tokio::net::TcpListener;
use utoipa::OpenApi;
use utoipa_axum::{router::OpenApiRouter, routes};
use utoipa_swagger_ui::SwaggerUi;
// tags
use v1::auth::AUTH_TAG;
mod v1;
mod structs;
mod state;
mod db;
#[derive(OpenApi)]
#[openapi(
tags(
(name = AUTH_TAG, description = "Authentication API endpoints"),
// (name = CUSTOMER_TAG, description = "Customer API endpoints"),
// (name = ORDER_TAG, description = "Order API endpoints")
)
),
)]
struct ApiDoc;
/// Get health of the API.
#[utoipa::path(
method(get, head),
get,
path = "/.well-known/health-check",
responses(
(status = OK, description = "Success", body = str, content_type = "text/plain")
@@ -27,22 +34,36 @@ async fn health_check() -> &'static str {
"ok"
}
#[utoipa::path(
get,
path = "/",
responses(
(status = OK, description = "Success", body = str, content_type = "text/plain")
)
)]
async fn index() -> &'static str {
"ok 200"
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
let db = db::db().await?;
let state = state::AppState { db: Arc::new(db) };
let port: u16 = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string()).parse()?;
let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
.routes(routes!(health_check))
// .nest("/api/customer", customer::router())
// .nest("/api/order", order::router())
// .routes(routes!(
// inner::secret_handlers::get_secret,
// inner::secret_handlers::post_secret
// ))
.routes(routes!(index))
.with_state(state.clone())
.nest("/api/v1/auth", v1::auth::router(state.clone()))
.split_for_parts();
let router = router.merge(SwaggerUi::new("/swagger-ui").url("/apidoc/openapi.json", api));
let router = router.merge(SwaggerUi::new("/docs").url("/docs/openapi.json", api));
println!("Listening on http://localhost:8080");
let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, 8080)).await?;
println!("Listening on http://localhost:{port}");
let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await?;
axum::serve(listener, router).await?;
Ok(())

8
src/state.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::sync::Arc;
#[derive(Clone)]
pub struct AppState {
pub db: DB,
}
pub type DB = Arc<sqlx::Pool<sqlx::Postgres>>;

1
src/structs/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod users;

9
src/structs/users.rs Normal file
View File

@@ -0,0 +1,9 @@
pub struct User {
pub id: uuid::Uuid,
pub real_name: String,
pub username: String,
pub email: String,
pub password_hash: String,
pub is_admin: bool,
pub created_at: chrono::NaiveDateTime,
}

View File

@@ -1,3 +1,13 @@
use crate::state::AppState;
pub(super) use super::*;
pub mod signup;
pub const AUTH_TAG: &str = "auth";
pub fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.routes(routes!(signup::signup))
.with_state(state)
}

View File

@@ -1,7 +1,11 @@
use axum::{extract::State, response::Response};
use crate::state::AppState;
use super::*;
// /// Get customer
// ///
// /// Just return a static Customer object
// #[utoipa::path(get, path = "", responses((status = OK, body = Customer)), tag = super::CUSTOMER_TAG)]
// pub async fn signup() -> Json<Customer> {}
/// Sign up
#[utoipa::path(get, path = "/signup", responses((status = OK, body = String)), tag = super::AUTH_TAG)]
pub async fn signup(State(state): State<AppState>) -> Response<String> {
Response::new("Hello, World!".to_string())
}