Files
music-agregator/src/api/mod.rs
T
2026-04-28 18:05:32 +02:00

87 lines
2.1 KiB
Rust

use axum::{
extract::{Path, Query, State},
http::StatusCode,
routing::{delete, get, post},
Json, Router,
};
use serde::Deserialize;
use uuid::Uuid;
use crate::models::{CreateTrack, Track};
use crate::AppState;
pub fn routes(state: AppState) -> Router {
Router::new()
.route("/tracks", get(list_tracks))
.route("/tracks", post(create_track))
.route("/tracks/:id", get(get_track))
.route("/tracks/:id", delete(delete_track))
.route("/tracks/search", get(search_tracks))
.route("/stats", get(get_stats))
.with_state(state)
}
async fn list_tracks(State(state): State<AppState>) -> Json<Vec<Track>> {
let agg = state.read().await;
Json(agg.get_all().to_vec())
}
async fn create_track(
State(state): State<AppState>,
Json(input): Json<CreateTrack>,
) -> (StatusCode, Json<Track>) {
let mut agg = state.write().await;
let track = agg.add_track(input.into());
(StatusCode::CREATED, Json(track))
}
async fn get_track(
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> Result<Json<Track>, StatusCode> {
let agg = state.read().await;
agg.get_by_id(id)
.cloned()
.map(Json)
.ok_or(StatusCode::NOT_FOUND)
}
async fn delete_track(
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> StatusCode {
let mut agg = state.write().await;
if agg.delete(id) {
StatusCode::NO_CONTENT
} else {
StatusCode::NOT_FOUND
}
}
#[derive(Deserialize)]
struct SearchQuery {
artist: String,
}
async fn search_tracks(
State(state): State<AppState>,
Query(query): Query<SearchQuery>,
) -> Json<Vec<Track>> {
let agg = state.read().await;
Json(agg.search_by_artist(&query.artist).into_iter().cloned().collect())
}
#[derive(serde::Serialize)]
struct Stats {
track_count: usize,
total_duration_secs: u32,
}
async fn get_stats(State(state): State<AppState>) -> Json<Stats> {
let agg = state.read().await;
Json(Stats {
track_count: agg.get_all().len(),
total_duration_secs: agg.total_duration(),
})
}