feat(cnnl-service): 添加根路径 API 文档页面
- 新增 GET / 路由,返回 HTML 格式的 API 文档页面 - 页面展示所有 5 个 API 端点说明 - 深色主题,符合 NAC 技术风格 - 包含 curl 快速示例和服务信息卡片 - 修复浏览器访问根路径返回 404 的问题
This commit is contained in:
parent
9b8a21b321
commit
c57b5216f7
|
|
@ -394,6 +394,229 @@ async fn handle_version(_state: web::Data<AppState>) -> impl Responder {
|
|||
HttpResponse::Ok().json(ApiResponse::ok(version, 0))
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// 根路径 - API 文档页面
|
||||
// ============================================================
|
||||
async fn handle_root() -> impl Responder {
|
||||
let html = r#"<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NAC CNNL 编译服务</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #0a0e1a;
|
||||
color: #c9d1d9;
|
||||
min-height: 100vh;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.container { max-width: 900px; margin: 0 auto; }
|
||||
.header {
|
||||
text-align: center;
|
||||
padding: 60px 0 40px;
|
||||
border-bottom: 1px solid #21262d;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.logo {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #58a6ff, #3fb950, #f78166);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
.subtitle {
|
||||
color: #8b949e;
|
||||
font-size: 16px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
background: #1f6feb;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
margin-top: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.section { margin-bottom: 40px; }
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
color: #e6edf3;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #21262d;
|
||||
}
|
||||
.endpoint-grid { display: grid; gap: 12px; }
|
||||
.endpoint {
|
||||
background: #161b22;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 8px;
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
.method {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
min-width: 52px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.method.get { background: #1a7f37; color: #3fb950; border: 1px solid #238636; }
|
||||
.method.post { background: #1a4a7f; color: #58a6ff; border: 1px solid #1f6feb; }
|
||||
.endpoint-info { flex: 1; }
|
||||
.path {
|
||||
font-family: "SFMono-Regular", Consolas, monospace;
|
||||
font-size: 14px;
|
||||
color: #e6edf3;
|
||||
font-weight: 600;
|
||||
}
|
||||
.desc { color: #8b949e; font-size: 13px; margin-top: 4px; }
|
||||
.code-block {
|
||||
background: #161b22;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
font-family: "SFMono-Regular", Consolas, monospace;
|
||||
font-size: 13px;
|
||||
overflow-x: auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.code-block .key { color: #79c0ff; }
|
||||
.code-block .str { color: #a5d6ff; }
|
||||
.code-block .num { color: #f2cc60; }
|
||||
.code-block .bool { color: #ff7b72; }
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.info-card {
|
||||
background: #161b22;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
}
|
||||
.info-label { color: #8b949e; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.info-value { color: #e6edf3; font-size: 15px; font-weight: 600; margin-top: 4px; }
|
||||
.footer {
|
||||
text-align: center;
|
||||
color: #484f58;
|
||||
font-size: 13px;
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid #21262d;
|
||||
margin-top: 40px;
|
||||
}
|
||||
a { color: #58a6ff; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="logo">NAC CNNL</div>
|
||||
<div class="subtitle">宪政神经网络语言编译服务</div>
|
||||
<div class="badge">v0.1.0 · 运行中</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>API 端点</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<span class="method post">POST</span>
|
||||
<div class="endpoint-info">
|
||||
<div class="path">/api/v1/compile</div>
|
||||
<div class="desc">编译 CNNL 源代码,生成 NVM 字节码和宪法状态文件</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<span class="method post">POST</span>
|
||||
<div class="endpoint-info">
|
||||
<div class="path">/api/v1/parse</div>
|
||||
<div class="desc">解析 CNNL 源代码,返回抽象语法树(AST)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<span class="method post">POST</span>
|
||||
<div class="endpoint-info">
|
||||
<div class="path">/api/v1/validate</div>
|
||||
<div class="desc">验证 CNNL 语法正确性,不生成字节码</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<span class="method get">GET</span>
|
||||
<div class="endpoint-info">
|
||||
<div class="path">/api/v1/health</div>
|
||||
<div class="desc">服务健康检查,返回运行状态和运行时长</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<span class="method get">GET</span>
|
||||
<div class="endpoint-info">
|
||||
<div class="path">/api/v1/version</div>
|
||||
<div class="desc">服务版本信息</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>快速示例</h2>
|
||||
<div class="code-block">
|
||||
<span style="color:#8b949e"># 编译一个 CNNL 条款</span>
|
||||
curl -X POST https://cnnl.newassetchain.io/api/v1/compile \
|
||||
-H <span class="str">"Content-Type: application/json"</span> \
|
||||
-d <span class="str">'{
|
||||
"source": "clause XTZH_GOLD_COVERAGE {\n level: eternal\n title: \"黄金储备覆盖率底线\"\n parameter XTZH_GOLD_COVERAGE_MIN: f64 = 1.25\n}",
|
||||
"generate_state": true
|
||||
}'</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>服务信息</h2>
|
||||
<div class="info-grid">
|
||||
<div class="info-card">
|
||||
<div class="info-label">服务名称</div>
|
||||
<div class="info-value">nac-cnnl-service</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-label">编译器版本</div>
|
||||
<div class="info-value">CNNL v0.1.0</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-label">目标虚拟机</div>
|
||||
<div class="info-value">NVM (NAC VM)</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div class="info-label">协议</div>
|
||||
<div class="info-value">HTTPS / TLS 1.3</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>NAC NewAssetChain · CNNL 宪政神经网络语言 · <a href="https://git.newassetchain.io/nacadmin/NAC_Blockchain">源代码仓库</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>"#;
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 主函数
|
||||
// ============================================================
|
||||
|
|
@ -420,6 +643,7 @@ async fn main() -> std::io::Result<()> {
|
|||
.app_data(app_state.clone())
|
||||
.app_data(web::JsonConfig::default().limit(1024 * 1024)) // 1MB 请求体限制
|
||||
// API 路由
|
||||
.route("/", web::get().to(handle_root))
|
||||
.route("/api/v1/compile", web::post().to(handle_compile))
|
||||
.route("/api/v1/parse", web::post().to(handle_parse))
|
||||
.route("/api/v1/validate", web::post().to(handle_validate))
|
||||
|
|
|
|||
Loading…
Reference in New Issue