bobashare_web/api/v1/
mod.rs1use std::error::Error;
4
5use axum::{
6 response::{IntoResponse, Response},
7 routing::{delete, get, put},
8 Json, Router,
9};
10use hyper::StatusCode;
11use serde_json::json;
12use tracing::{event, Level};
13
14use crate::AppState;
15
16pub mod delete;
17pub mod info;
18pub mod upload;
19
20pub fn router() -> Router<&'static AppState> {
27 Router::new()
28 .route("/info/{id}", get(info::info))
29 .route("/upload/{filename}", put(upload::put))
30 .route("/delete/{id}", delete(delete::delete))
31}
32
33pub trait ApiErrorExt: Error + Sized + Send + Sync + 'static {
36 fn into_response_with_code(self, code: StatusCode) -> Response {
39 let mut error_msg = self.to_string(); let mut err_buf = self.source();
42 while let Some(e) = err_buf {
43 error_msg += &format!(": {e}");
44 err_buf = e.source();
45 }
46
47 if code.is_server_error() {
48 event!(Level::ERROR, status = code.as_u16(), error = error_msg);
49 } else if code.is_client_error() {
50 event!(Level::WARN, status = code.as_u16(), error = error_msg);
51 } else {
52 event!(Level::INFO, status = code.as_u16(), error = error_msg);
53 }
54
55 let resp = json!({
56 "status": "error",
57 "error": serde_error::Error::new(&self),
58 "message": error_msg,
59 });
60 (code, Json(resp)).into_response()
61 }
62}
63impl<T> ApiErrorExt for T where T: Error + Send + Sync + 'static {}