Files
zero2prod/src/routes/posts.rs
2025-09-20 16:45:16 +02:00

75 lines
2.0 KiB
Rust

use crate::{
domain::PostEntry,
routes::AppError,
startup::AppState,
templates::{PostTemplate, PostsTemplate},
};
use anyhow::Context;
use askama::Template;
use axum::{
extract::{Path, State},
response::{Html, IntoResponse, Response},
};
use sqlx::PgPool;
use uuid::Uuid;
pub async fn list_posts(
State(AppState {
connection_pool, ..
}): State<AppState>,
) -> Result<Response, AppError> {
let posts = get_latest_posts(&connection_pool, 5)
.await
.context("Could not fetch latest posts")
.map_err(AppError::unexpected_page)?;
let template = PostsTemplate { posts };
Ok(Html(template.render().unwrap()).into_response())
}
async fn get_latest_posts(connection_pool: &PgPool, n: i64) -> Result<Vec<PostEntry>, sqlx::Error> {
sqlx::query_as!(
PostEntry,
r#"
SELECT p.post_id, u.username AS author, p.title, p.content, p.published_at
FROM posts p
LEFT JOIN users u ON p.author_id = u.user_id
ORDER BY p.published_at DESC
LIMIT $1
"#,
n
)
.fetch_all(connection_pool)
.await
}
pub async fn see_post(
State(AppState {
connection_pool, ..
}): State<AppState>,
Path(post_id): Path<Uuid>,
) -> Result<Response, AppError> {
let post = get_post(&connection_pool, post_id)
.await
.context(format!("Failed to fetch post #{}", post_id))
.map_err(AppError::unexpected_page)?
.to_html()
.context("Could not render markdown with extension.")?;
let template = PostTemplate { post };
Ok(Html(template.render().unwrap()).into_response())
}
async fn get_post(connection_pool: &PgPool, post_id: Uuid) -> Result<PostEntry, sqlx::Error> {
sqlx::query_as!(
PostEntry,
r#"
SELECT p.post_id, u.username AS author, p.title, p.content, p.published_at
FROM posts p
LEFT JOIN users u ON p.author_id = u.user_id
WHERE p.post_id = $1
"#,
post_id
)
.fetch_one(connection_pool)
.await
}