Skip to main content

tdm_server_rust/web/
doc_controller.rs

1//! API 文档接口 (Doc Controller)
2//!
3//! Swagger UI 托管和 OpenAPI JSON 端点。
4
5use axum::{
6    http::{header, StatusCode},
7    response::{Html, IntoResponse, Redirect, Response},
8    routing::get,
9    Router,
10};
11use crate::config::SpringdocConfig;
12
13/// 编译期嵌入的 OpenAPI 契约(与 Java smart-doc 生成物一致)
14const OPENAPI_JSON: &str = include_str!("../../assets/doc/openapi.json");
15
16/// Swagger UI 页面模板(占位符 __OPENAPI_URL__ / __OPERATIONS_SORTER__)
17const SWAGGER_UI_TEMPLATE: &str = r##"<!DOCTYPE html>
18<html lang="en">
19<head>
20  <meta charset="UTF-8">
21  <title>Swagger UI</title>
22  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.18.3/swagger-ui.css">
23</head>
24<body>
25<div id="swagger-ui"></div>
26<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.18.3/swagger-ui-bundle.js"></script>
27<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.18.3/swagger-ui-standalone-preset.js"></script>
28<script>
29window.onload = function () {
30  window.ui = SwaggerUIBundle({
31    url: "__OPENAPI_URL__",
32    dom_id: "#swagger-ui",
33    deepLinking: true,
34    presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
35    plugins: [SwaggerUIBundle.plugins.DownloadUrl],
36    layout: "StandaloneLayout",
37    operationsSorter: "__OPERATIONS_SORTER__"
38  });
39};
40</script>
41</body>
42</html>"##;
43
44/// 返回 OpenAPI JSON 文档
45#[tracing::instrument(skip_all, level = "info")]
46async fn openapi_json() -> Response {
47    (
48        StatusCode::OK,
49        [(header::CONTENT_TYPE, "application/json; charset=utf-8")],
50        OPENAPI_JSON,
51    )
52        .into_response()
53}
54
55/// `/doc/` 根路径重定向
56#[tracing::instrument(skip_all, level = "info")]
57async fn doc_root() -> Redirect {
58    Redirect::permanent("/doc/openapi.json")
59}
60
61/// 返回 Swagger UI HTML
62#[tracing::instrument(skip_all, level = "info")]
63fn build_swagger_ui_html(cfg: &SpringdocConfig) -> Html<String> {
64    let html = SWAGGER_UI_TEMPLATE
65        .replace("__OPENAPI_URL__", &cfg.swagger_ui.url)
66        .replace(
67            "__OPERATIONS_SORTER__",
68            &cfg.swagger_ui.operations_sorter,
69        );
70    Html(html)
71}
72
73/// 注册文档路由(仅 dev / dev-h2 调用)
74pub fn routes(cfg: SpringdocConfig) -> Router {
75    Router::new()
76        .route("/doc/openapi.json", get(openapi_json))
77        .route("/doc/", get(doc_root))
78        .route(
79            "/swagger-ui.html",
80            get({
81                let cfg = cfg.clone();
82                move || async move { build_swagger_ui_html(&cfg) }
83            }),
84        )
85}