Refactor to use more idiomatic http pattern

This commit is contained in:
Alex Selimov 2026-03-19 14:01:20 -04:00
parent 3bff31ff98
commit f81b29c5e9

View file

@ -1,12 +1,17 @@
use axum::{Json, Router, extract::State, http::StatusCode, response::IntoResponse, routing::post}; use axum::{
Router,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
routing::post,
};
use axum_extra::extract::{CookieJar, cookie::Cookie}; use axum_extra::extract::{CookieJar, cookie::Cookie};
use serde::Deserialize;
use uuid::Uuid; use uuid::Uuid;
use crate::{state::AppState, votes::repository::insert_new_vote}; use crate::{state::AppState, votes::repository::insert_new_vote};
pub fn router() -> Router<AppState> { pub fn router() -> Router<AppState> {
Router::new().route("/vote", post(upvote_handler)) Router::new().route("/posts/{slug}/vote", post(upvote_handler))
} }
fn get_or_init_voter_id(jar: CookieJar) -> (CookieJar, Uuid) { fn get_or_init_voter_id(jar: CookieJar) -> (CookieJar, Uuid) {
@ -30,19 +35,14 @@ fn get_or_init_voter_id(jar: CookieJar) -> (CookieJar, Uuid) {
} }
} }
#[derive(Deserialize)]
struct UpvotePayload {
slug: String,
}
async fn upvote_handler( async fn upvote_handler(
jar: CookieJar, jar: CookieJar,
Path(slug): Path<String>,
State(state): State<AppState>, State(state): State<AppState>,
Json(body): Json<UpvotePayload>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let (jar, voter_id) = get_or_init_voter_id(jar); let (jar, voter_id) = get_or_init_voter_id(jar);
match insert_new_vote(&body.slug, &voter_id, &state.db).await { match insert_new_vote(&slug, &voter_id, &state.db).await {
Ok(()) => (StatusCode::OK, jar, "Successfully upvoted"), Ok(()) => (StatusCode::OK, jar, "Successfully upvoted"),
Err(err) => { Err(err) => {
println!("{err}"); println!("{err}");
@ -98,9 +98,9 @@ mod tests {
let request = Request::builder() let request = Request::builder()
.method("POST") .method("POST")
.uri("/vote") .uri(format!("/posts/{slug}/vote"))
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, "application/json")
.body(Body::from(format!(r#"{{"slug":"{slug}"}}"#))) .body(Body::empty())
.unwrap(); .unwrap();
let response = app.oneshot(request).await.unwrap(); let response = app.oneshot(request).await.unwrap();
@ -128,10 +128,10 @@ mod tests {
let app = crate::app(test_state(db.clone())); let app = crate::app(test_state(db.clone()));
let request = Request::builder() let request = Request::builder()
.method("POST") .method("POST")
.uri("/vote") .uri(format!("/posts/{slug}/vote"))
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, "application/json")
.header(header::COOKIE, &cookie) .header(header::COOKIE, &cookie)
.body(Body::from(format!(r#"{{"slug":"{slug}"}}"#))) .body(Body::empty())
.unwrap(); .unwrap();
let response = app.oneshot(request).await.unwrap(); let response = app.oneshot(request).await.unwrap();
@ -151,10 +151,10 @@ mod tests {
let app = crate::app(test_state(db.clone())); let app = crate::app(test_state(db.clone()));
let request = Request::builder() let request = Request::builder()
.method("POST") .method("POST")
.uri("/vote") .uri(format!("/posts/{slug}/vote"))
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, "application/json")
.header(header::COOKIE, "voter_id=not-a-uuid") .header(header::COOKIE, "voter_id=not-a-uuid")
.body(Body::from(format!(r#"{{"slug":"{slug}"}}"#))) .body(Body::empty())
.unwrap(); .unwrap();
let response = app.oneshot(request).await.unwrap(); let response = app.oneshot(request).await.unwrap();