1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
use std::sync::Arc;
use axum::{
extract::State,
http::{StatusCode, Uri},
Json,
};
use axum_extra::routing::{RouterExt, TypedPath};
use serde::Deserialize;
use crate::{model::User, state::AppState, Error};
pub fn router(state: AppState) -> axum::Router {
axum::Router::new()
// .route("/api/user", get(get_user))
.typed_get(HealthCheck::get)
.typed_get(UserId::get)
.fallback(fallback)
.with_state(Arc::new(state))
}
#[derive(Debug, Deserialize, TypedPath)]
#[typed_path("/api/healthcheck")]
pub struct HealthCheck;
impl HealthCheck {
pub async fn get(self) -> Json<serde_json::Value> {
const MESSAGE: &str = "Unnamed server";
let json_response = serde_json::json!({
"status": "success",
"message": MESSAGE
});
Json(json_response)
}
}
#[derive(Debug, Deserialize, TypedPath)]
#[typed_path("/api/user/:uuid")]
pub struct UserId {
pub uuid: uuid::Uuid,
}
impl UserId {
/// Get a user via their `id`
#[tracing::instrument(ret, skip(data))]
pub async fn get(
self,
State(data): State<Arc<AppState>>,
) -> Result<Json<serde_json::Value>, Error> {
sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", self.uuid)
.fetch_optional(&data.db_pool)
.await?
.ok_or_else(|| Error::UserNotFound(self.uuid))
.map(User::into_query_response)
}
}
pub async fn fallback(uri: Uri) -> (StatusCode, String) {
(StatusCode::NOT_FOUND, format!("Route not found: {uri}"))
}
#[cfg(test)]
mod tests {
use super::*;
use axum_test::TestServer;
#[tokio::test]
async fn test_fallback() -> Result<(), Box<dyn std::error::Error>> {
let server = TestServer::new(axum::Router::new().fallback(fallback))?;
let response = server.get("/fallback").await;
assert_eq!(StatusCode::NOT_FOUND, response.status_code());
Ok(())
}
}
|