diff options
| author | rtkay123 <dev@kanjala.com> | 2025-11-23 12:38:49 +0200 |
|---|---|---|
| committer | rtkay123 <dev@kanjala.com> | 2025-11-23 12:38:49 +0200 |
| commit | ae72e4f8d4ccb6d5ed71e17d6b2ffb0ac8876e0a (patch) | |
| tree | 89e4c44a9e3e0c6cd32976fdc69172d42375fcf2 | |
| parent | 432a5061c0b910821635825021a37f798e0ce26c (diff) | |
| download | sellershut-ae72e4f8d4ccb6d5ed71e17d6b2ffb0ac8876e0a.tar.bz2 sellershut-ae72e4f8d4ccb6d5ed71e17d6b2ffb0ac8876e0a.zip | |
feat: apidoc
| -rw-r--r-- | Cargo.lock | 287 | ||||
| -rw-r--r-- | crates/sellershut/Cargo.toml | 15 | ||||
| -rw-r--r-- | crates/sellershut/src/config.rs (renamed from crates/sellershut/src/config/mod.rs) | 14 | ||||
| -rw-r--r-- | crates/sellershut/src/logging.rs | 19 | ||||
| -rw-r--r-- | crates/sellershut/src/main.rs | 42 | ||||
| -rw-r--r-- | crates/sellershut/src/server.rs | 42 | ||||
| -rw-r--r-- | crates/sellershut/src/server/doc.rs | 11 | ||||
| -rw-r--r-- | crates/sellershut/src/server/middleware.rs | 2 | ||||
| -rw-r--r-- | crates/sellershut/src/server/middleware/request_id.rs | 11 | ||||
| -rw-r--r-- | crates/sellershut/src/server/middleware/timeout.rs | 15 | ||||
| -rw-r--r-- | crates/sellershut/src/server/routes.rs | 15 |
11 files changed, 437 insertions, 36 deletions
@@ -53,6 +53,12 @@ dependencies = [ ] [[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] name = "aho-corasick" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -127,6 +133,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + +[[package]] name = "async-lock" version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -373,6 +388,15 @@ dependencies = [ ] [[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] name = "crossbeam-channel" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -453,6 +477,17 @@ dependencies = [ ] [[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] name = "derive_builder" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -575,6 +610,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "libz-rs-sys", + "miniz_oxide", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1002,6 +1048,8 @@ checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown", + "serde", + "serde_core", ] [[package]] @@ -1073,6 +1121,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] +name = "libz-rs-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" +dependencies = [ + "zlib-rs", +] + +[[package]] name = "litemap" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1127,6 +1184,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] name = "mio" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1255,6 +1332,12 @@ dependencies = [ ] [[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] name = "pem-rfc7468" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1593,6 +1676,40 @@ dependencies = [ ] [[package]] +name = "rust-embed" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.111", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1655,6 +1772,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1669,9 +1795,16 @@ dependencies = [ "axum", "clap", "tokio", + "tower", "tower-http", "tracing", "tracing-subscriber", + "utoipa", + "utoipa-axum", + "utoipa-rapidoc", + "utoipa-redoc", + "utoipa-scalar", + "utoipa-swagger-ui", ] [[package]] @@ -1793,6 +1926,12 @@ dependencies = [ ] [[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] name = "slab" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2054,6 +2193,7 @@ dependencies = [ "tower-layer", "tower-service", "tracing", + "uuid", ] [[package]] @@ -2143,6 +2283,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2179,6 +2325,96 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] +name = "utoipa" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-axum" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c25bae5bccc842449ec0c5ddc5cbb6a3a1eaeac4503895dc105a1138f8234a0" +dependencies = [ + "axum", + "paste", + "tower-layer", + "tower-service", + "utoipa", +] + +[[package]] +name = "utoipa-gen" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "utoipa-rapidoc" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f8f5abd341cce16bb4f09a8bafc087d4884a004f25fb980e538d51d6501dab" +dependencies = [ + "axum", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-redoc" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6427547f6db7ec006cbbef95f7565952a16f362e298b416d2d497d9706fef72d" +dependencies = [ + "axum", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-scalar" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59559e1509172f6b26c1cdbc7247c4ddd1ac6560fe94b584f81ee489b141f719" +dependencies = [ + "axum", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "9.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d047458f1b5b65237c2f6dc6db136945667f40a7668627b3490b9513a3d43a55" +dependencies = [ + "axum", + "base64", + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa", + "zip", +] + +[[package]] name = "uuid" version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2202,6 +2438,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2326,6 +2572,15 @@ dependencies = [ ] [[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] name = "windows-core" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2654,3 +2909,35 @@ dependencies = [ "quote", "syn 2.0.111", ] + +[[package]] +name = "zip" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308" +dependencies = [ + "arbitrary", + "crc32fast", + "flate2", + "indexmap", + "memchr", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] diff --git a/crates/sellershut/Cargo.toml b/crates/sellershut/Cargo.toml index 9fcf378..aee606e 100644 --- a/crates/sellershut/Cargo.toml +++ b/crates/sellershut/Cargo.toml @@ -13,6 +13,19 @@ anyhow = "1.0.100" axum = { version = "0.8.7", features = ["macros"] } clap = { version = "4.5.53", features = ["derive", "env"] } tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread", "signal"] } -tower-http = { version = "0.6.6", features = ["trace", "timeout"] } +tower = "0.5.2" +tower-http = { version = "0.6.6", features = ["propagate-header", "request-id", "trace", "timeout"] } tracing.workspace = true tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } +utoipa = "5.4.0" +utoipa-axum = "0.2.0" +utoipa-rapidoc = { version = "6.0.0", features = ["axum"], optional = true } +utoipa-redoc = { version = "6.0.0", optional = true, features = ["axum"] } +utoipa-scalar = { version = "0.3.0", features = ["axum"], optional = true } +utoipa-swagger-ui = { version = "9.0.2", features = ["axum"], optional = true } + +[features] +redoc = ["dep:utoipa-redoc"] +rapidoc = ["dep:utoipa-rapidoc"] +scalar = ["dep:utoipa-scalar"] +swagger-ui = ["dep:utoipa-swagger-ui"] diff --git a/crates/sellershut/src/config/mod.rs b/crates/sellershut/src/config.rs index 9ce7b2d..65383a6 100644 --- a/crates/sellershut/src/config/mod.rs +++ b/crates/sellershut/src/config.rs @@ -5,20 +5,26 @@ use std::path::PathBuf; use clap::Parser; use logging::LogLevel; +pub const LOG_LEVEL: &str = "LOG_LEVEL"; + #[derive(Parser, Debug)] #[command(version, about, long_about = None)] pub struct Cli { /// Sets the port the server listens on - #[arg(default_value_t = 2210, env = "PORT")] - port: u16, + #[arg(short, long, default_value_t = 2210, env = "PORT")] + pub port: u16, - /// Sets the port the server listens on - #[arg(short, long, value_enum, env = "LOG_LEVEL", default_value_t = LogLevel::Debug)] + /// Sets the application log level + #[arg(short, long, value_enum, env = LOG_LEVEL, default_value_t = LogLevel::Debug)] log_level: LogLevel, /// Sets a custom config file #[arg(short, long, value_name = "FILE")] config: Option<PathBuf>, + + /// Request timeout duration (in seconds) + #[arg(short, long, default_value_t = 10, env = "TIMEOUT_DURATION")] + pub timeout_duration: u64, } impl Cli { diff --git a/crates/sellershut/src/logging.rs b/crates/sellershut/src/logging.rs new file mode 100644 index 0000000..89b8686 --- /dev/null +++ b/crates/sellershut/src/logging.rs @@ -0,0 +1,19 @@ +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; + +use crate::config::{Cli, LOG_LEVEL}; + +pub fn initialise_logging(config: &Cli) { + tracing_subscriber::registry() + .with( + tracing_subscriber::EnvFilter::try_from_env(LOG_LEVEL).unwrap_or_else(|_| { + format!( + "{}={},tower_http=debug,axum=trace", + env!("CARGO_CRATE_NAME"), + config.log_level() + ) + .into() + }), + ) + .with(tracing_subscriber::fmt::layer()) + .init(); +} diff --git a/crates/sellershut/src/main.rs b/crates/sellershut/src/main.rs index 9736986..07e6193 100644 --- a/crates/sellershut/src/main.rs +++ b/crates/sellershut/src/main.rs @@ -1,45 +1,25 @@ mod config; +mod logging; +mod server; -use std::time::Duration; +use std::net::{Ipv6Addr, SocketAddr}; -use axum::{Router, routing::get}; use clap::Parser; use tokio::{net::TcpListener, signal}; -use tower_http::{timeout::TimeoutLayer, trace::TraceLayer}; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +use tracing::info; + +use crate::logging::initialise_logging; #[tokio::main] async fn main() -> anyhow::Result<()> { let config = config::Cli::parse(); - dbg!(&config); - - tracing_subscriber::registry() - .with( - tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { - format!( - "{}={},tower_http=debug,axum=trace", - env!("CARGO_CRATE_NAME"), - config.log_level() - ) - .into() - }), - ) - .with(tracing_subscriber::fmt::layer().without_time()) - .init(); + initialise_logging(&config); - // Create a regular axum app. - let app = Router::new() - .route("/slow", get(|| tokio::time::sleep(Duration::from_secs(5)))) - .route("/forever", get(std::future::pending::<()>)) - .layer(( - TraceLayer::new_for_http(), - // Graceful shutdown will wait for outstanding requests to complete. Add a timeout so - // requests don't hang forever. - TimeoutLayer::new(Duration::from_secs(10)), - )); + let app = server::router(&config); - // Create a `TcpListener` using tokio. - let listener = TcpListener::bind("0.0.0.0:3000").await?; + let addr = SocketAddr::from((Ipv6Addr::UNSPECIFIED, config.port)); + info!(port = addr.port(), "starting server"); + let listener = TcpListener::bind(addr).await?; // Run the server with graceful shutdown axum::serve(listener, app) diff --git a/crates/sellershut/src/server.rs b/crates/sellershut/src/server.rs new file mode 100644 index 0000000..cee6146 --- /dev/null +++ b/crates/sellershut/src/server.rs @@ -0,0 +1,42 @@ +mod doc; +mod middleware; +mod routes; + +use axum::Router; +use utoipa::OpenApi as _; +use utoipa_axum::{router::OpenApiRouter, routes}; + +#[cfg(feature = "redoc")] +use utoipa_redoc::Servable as _; +#[cfg(feature = "scalar")] +use utoipa_scalar::Servable as _; + +use crate::{config::Cli, server::doc::ApiDoc}; + +pub fn router(config: &Cli) -> Router { + let (router, _api) = OpenApiRouter::with_openapi(ApiDoc::openapi()) + .routes(routes!(routes::health_check)) + .split_for_parts(); + + #[cfg(feature = "swagger-ui")] + let router = router.merge( + utoipa_swagger_ui::SwaggerUi::new("/swagger-ui") + .url("/api-docs/swaggerdoc.json", _api.clone()), + ); + + #[cfg(feature = "redoc")] + let router = router.merge(utoipa_redoc::Redoc::with_url("/redoc", _api.clone())); + + #[cfg(feature = "rapidoc")] + let router = router.merge( + utoipa_rapidoc::RapiDoc::with_openapi("/api-docs/rapidoc.json", _api.clone()) + .path("/rapidoc"), + ); + + #[cfg(feature = "scalar")] + let router = router.merge(utoipa_scalar::Scalar::with_url("/scalar", _api)); + + let router = middleware::timeout::apply(router, config.timeout_duration); + + middleware::request_id::apply(router) +} diff --git a/crates/sellershut/src/server/doc.rs b/crates/sellershut/src/server/doc.rs new file mode 100644 index 0000000..11b561e --- /dev/null +++ b/crates/sellershut/src/server/doc.rs @@ -0,0 +1,11 @@ +use utoipa::OpenApi; + +pub(super) const HEALTH: &str = "HEALTH"; + +#[derive(OpenApi)] +#[openapi( + tags( + (name = HEALTH, description = "Check API health"), + ) +)] +pub struct ApiDoc; diff --git a/crates/sellershut/src/server/middleware.rs b/crates/sellershut/src/server/middleware.rs new file mode 100644 index 0000000..0c44376 --- /dev/null +++ b/crates/sellershut/src/server/middleware.rs @@ -0,0 +1,2 @@ +pub(super) mod request_id; +pub(super) mod timeout; diff --git a/crates/sellershut/src/server/middleware/request_id.rs b/crates/sellershut/src/server/middleware/request_id.rs new file mode 100644 index 0000000..cce6898 --- /dev/null +++ b/crates/sellershut/src/server/middleware/request_id.rs @@ -0,0 +1,11 @@ +use axum::{Router, http::HeaderName}; +use tower_http::propagate_header::PropagateHeaderLayer; +use tracing::trace; + +pub fn apply(router: Router) -> Router { + trace!("applying x-request-id middleware"); + + router.layer(PropagateHeaderLayer::new(HeaderName::from_static( + "x-request-id", + ))) +} diff --git a/crates/sellershut/src/server/middleware/timeout.rs b/crates/sellershut/src/server/middleware/timeout.rs new file mode 100644 index 0000000..ff39c6a --- /dev/null +++ b/crates/sellershut/src/server/middleware/timeout.rs @@ -0,0 +1,15 @@ +use std::time::Duration; + +use axum::Router; +use tower_http::{timeout::TimeoutLayer, trace::TraceLayer}; +use tracing::trace; + +pub fn apply(router: Router, duration: u64) -> Router { + trace!(seconds = duration, "applying timeout middleware"); + router.layer(( + TraceLayer::new_for_http(), + // Graceful shutdown will wait for outstanding requests to complete. Add a timeout so + // requests don't hang forever. + TimeoutLayer::new(Duration::from_secs(duration)), + )) +} diff --git a/crates/sellershut/src/server/routes.rs b/crates/sellershut/src/server/routes.rs new file mode 100644 index 0000000..e5d1031 --- /dev/null +++ b/crates/sellershut/src/server/routes.rs @@ -0,0 +1,15 @@ +/// Get health of the API. +#[utoipa::path( + method(get), + path = "/", + tag = super::doc::HEALTH, + responses( + (status = OK, description = "Success", body = str, content_type = "text/plain") + ) +)] +pub async fn health_check() -> impl axum::response::IntoResponse { + let name = env!("CARGO_PKG_NAME"); + let ver = env!("CARGO_PKG_VERSION"); + + format!("{name} v{ver} is live") +} |
