tdm_server_rust/web/
mod.rs1pub mod author_controller;
29pub mod doc_controller;
32pub mod episode_controller;
34pub mod evaluation_controller;
36pub mod login_controller;
38pub mod magazine_controller;
40pub mod manga_benefit_controller;
42pub mod manga_controller;
44pub mod member_controller;
46pub mod oss_controller;
48pub mod questionnaire_controller;
50pub mod reward_controller;
52pub mod task_tracking_controller;
54
55use crate::{
56 app::AppState,
57 dev,
58 middleware::{auth_middleware, debug_log_middleware, error_log_middleware},
59 telemetry::telemetry_http_span_middleware,
60};
61use axum::http::header;
62use axum::http::{HeaderName, StatusCode};
63use axum::middleware;
64use axum::response::IntoResponse;
65use axum::Router;
66use tower_http::cors::CorsLayer;
67
68pub fn create_router(state: AppState) -> Router {
70 let api = Router::new()
71 .merge(login_controller::routes())
72 .nest("/members", member_controller::routes())
73 .nest("/authors", author_controller::routes())
74 .nest("/magazines", magazine_controller::routes())
75 .nest("/evaluations", evaluation_controller::routes())
76 .nest("/questionnaires", questionnaire_controller::routes())
77 .nest("/mangas", manga_controller::routes())
78 .nest("/episodes", episode_controller::routes())
79 .nest("/manga/benefits", manga_benefit_controller::routes())
80 .nest("/reward", reward_controller::routes())
81 .nest("/oss", oss_controller::routes())
82 .nest("/admin/taskTracking", task_tracking_controller::routes());
83
84 let api = api
85 .fallback(api_not_found)
86 .layer(middleware::from_fn(error_log_middleware))
87 .layer(middleware::from_fn_with_state(state.clone(), auth_middleware))
88 .with_state(state.clone());
89
90 let cors = CorsLayer::permissive().expose_headers([
91 HeaderName::from_static("server-timing"),
92 header::LOCATION,
93 HeaderName::from_static("x-download-filename"),
94 header::CONTENT_DISPOSITION,
95 ]);
96
97 let mut app = Router::new()
98 .nest("/api", api)
99 .layer(cors)
100 .with_state(state.clone());
101
102 if state.config.telemetry.enabled {
103 app = app.layer(middleware::from_fn(telemetry_http_span_middleware));
104 }
105
106 if matches!(state.config.profile.as_str(), "dev" | "dev-h2") {
107 let springdoc = state.config.springdoc.clone();
108 app = app.merge(doc_controller::routes(springdoc));
109 app = app.merge(dev::routes(state.clone()));
110 app = app.layer(middleware::from_fn(debug_log_middleware));
111 }
112
113 app
114}
115
116#[tracing::instrument(skip_all, level = "info")]
118async fn api_not_found() -> impl IntoResponse {
119 (
120 StatusCode::NOT_FOUND,
121 r#"{"code":404,"msg":"接口不存在","data":null}"#,
122 )
123}