Skip to main content

oversync_api/
handlers.rs

1use std::sync::Arc;
2
3use axum::Json;
4use axum::extract::{Path, State};
5use axum::http::StatusCode;
6use axum::response::IntoResponse;
7
8use crate::state::ApiState;
9use crate::types::*;
10
11#[utoipa::path(
12	get,
13	path = "/health",
14	responses(
15		(status = 200, description = "Service is healthy", body = HealthResponse)
16	)
17)]
18pub async fn health() -> Json<HealthResponse> {
19	Json(HealthResponse {
20		status: "ok",
21		version: env!("CARGO_PKG_VERSION"),
22	})
23}
24
25#[utoipa::path(
26	get,
27	path = "/sources",
28	responses(
29		(status = 200, description = "List configured sources", body = SourceListResponse)
30	)
31)]
32pub async fn list_sources(State(state): State<Arc<ApiState>>) -> Json<SourceListResponse> {
33	Json(SourceListResponse {
34		sources: state.sources_info(),
35	})
36}
37
38#[utoipa::path(
39	get,
40	path = "/sources/{name}",
41	params(("name" = String, Path, description = "Source name")),
42	responses(
43		(status = 200, description = "Source details", body = SourceInfo),
44		(status = 404, description = "Source not found", body = ErrorResponse)
45	)
46)]
47pub async fn get_source(
48	State(state): State<Arc<ApiState>>,
49	Path(name): Path<String>,
50) -> Result<Json<SourceInfo>, impl IntoResponse> {
51	state
52		.sources_info()
53		.into_iter()
54		.find(|s| s.name == name)
55		.map(Json)
56		.ok_or_else(|| {
57			(
58				StatusCode::NOT_FOUND,
59				Json(ErrorResponse {
60					error: format!("source not found: {name}"),
61				}),
62			)
63		})
64}
65
66#[utoipa::path(
67	get,
68	path = "/sinks",
69	responses(
70		(status = 200, description = "List configured sinks", body = SinkListResponse)
71	)
72)]
73pub async fn list_sinks(State(state): State<Arc<ApiState>>) -> Json<SinkListResponse> {
74	Json(SinkListResponse {
75		sinks: state.sinks_info(),
76	})
77}
78
79#[utoipa::path(
80	get,
81	path = "/pipes",
82	responses(
83		(status = 200, description = "List configured pipes", body = PipeListResponse)
84	)
85)]
86pub async fn list_pipes(State(state): State<Arc<ApiState>>) -> Json<PipeListResponse> {
87	Json(PipeListResponse {
88		pipes: state.pipes_info(),
89	})
90}
91
92#[utoipa::path(
93	get,
94	path = "/pipes/{name}",
95	params(("name" = String, Path, description = "Pipe name")),
96	responses(
97		(status = 200, description = "Pipe details", body = PipeInfo),
98		(status = 404, description = "Pipe not found", body = ErrorResponse)
99	)
100)]
101pub async fn get_pipe(
102	State(state): State<Arc<ApiState>>,
103	Path(name): Path<String>,
104) -> Result<Json<PipeInfo>, impl IntoResponse> {
105	state
106		.pipes_info()
107		.into_iter()
108		.find(|p| p.name == name)
109		.map(Json)
110		.ok_or_else(|| {
111			(
112				StatusCode::NOT_FOUND,
113				Json(ErrorResponse {
114					error: format!("pipe not found: {name}"),
115				}),
116			)
117		})
118}