release(secrets-mcp): 0.5.10 — Web 模块化、性能与错误处理
- 拆分 web.rs 为 web/ 子模块;统一 client_ip 提取 - core: user_scope SQL 复用、env_map N+1 消除、FETCH_ALL 上限调整 - entries 列表页并行查询;PgPool 去 Arc;结构化 NotFound 等错误 - CI: SSH 私钥安全写入;crypto/hex 与依赖清理;MCP 输入长度校验 - AGENTS: API Key 明文存储设计说明
This commit is contained in:
73
crates/secrets-mcp/src/web/assets.rs
Normal file
73
crates/secrets-mcp/src/web/assets.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::State,
|
||||
http::{StatusCode, header},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
pub(super) fn text_asset_response(content: &'static str, content_type: &'static str) -> Response {
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, content_type)
|
||||
.header(header::CACHE_CONTROL, "public, max-age=86400")
|
||||
.body(Body::from(content))
|
||||
.expect("text asset response")
|
||||
}
|
||||
|
||||
pub(super) async fn robots_txt() -> Response {
|
||||
text_asset_response(
|
||||
include_str!("../../static/robots.txt"),
|
||||
"text/plain; charset=utf-8",
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) async fn llms_txt() -> Response {
|
||||
text_asset_response(
|
||||
include_str!("../../static/llms.txt"),
|
||||
"text/markdown; charset=utf-8",
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) async fn ai_txt() -> Response {
|
||||
llms_txt().await
|
||||
}
|
||||
|
||||
pub(super) async fn i18n_js() -> Response {
|
||||
text_asset_response(
|
||||
include_str!("../../templates/i18n.js"),
|
||||
"application/javascript; charset=utf-8",
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) async fn favicon_svg() -> Response {
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, "image/svg+xml")
|
||||
.header(header::CACHE_CONTROL, "public, max-age=86400")
|
||||
.body(Body::from(include_str!("../../static/favicon.svg")))
|
||||
.expect("favicon response")
|
||||
}
|
||||
|
||||
/// RFC 9728 — OAuth 2.0 Protected Resource Metadata.
|
||||
///
|
||||
/// Advertises that this server accepts Bearer tokens in the `Authorization`
|
||||
/// header. We deliberately omit `authorization_servers` because this service
|
||||
/// issues its own API keys (no external OAuth AS is involved). MCP clients
|
||||
/// that probe this endpoint will see the resource identifier and stop looking
|
||||
/// for a delegated OAuth flow.
|
||||
pub(super) async fn oauth_protected_resource_metadata(
|
||||
State(state): State<AppState>,
|
||||
) -> impl IntoResponse {
|
||||
let body = serde_json::json!({
|
||||
"resource": state.base_url,
|
||||
"bearer_methods_supported": ["header"],
|
||||
"resource_documentation": format!("{}/dashboard", state.base_url),
|
||||
});
|
||||
(
|
||||
StatusCode::OK,
|
||||
[(header::CONTENT_TYPE, "application/json")],
|
||||
axum::Json(body),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user