release: secrets-mcp 0.5.2
Some checks failed
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Successful in 6m7s
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Failing after 6s

Bump version: secrets-mcp-0.5.1 tag already existed while crates had further changes.

Made-with: Cursor
This commit is contained in:
2026-04-05 10:38:50 +08:00
parent aefad33870
commit dd24f7cc44
15 changed files with 787 additions and 66 deletions

View File

@@ -1,8 +1,11 @@
mod auth;
mod client_ip;
mod error;
mod logging;
mod oauth;
mod rate_limit;
mod tools;
mod validation;
mod web;
use std::net::SocketAddr;
@@ -153,10 +156,43 @@ async fn main() -> Result<()> {
);
// ── Router ────────────────────────────────────────────────────────────────
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any);
// CORS: restrict origins in production, allow all in development
let is_production = matches!(
load_env_var("SECRETS_ENV")
.as_deref()
.map(|s| s.to_ascii_lowercase())
.as_deref(),
Some("prod" | "production")
);
let cors = if is_production {
// Only use the origin part (scheme://host:port) of BASE_URL for CORS.
// Browsers send Origin without path, so including a path would cause mismatches.
let allowed_origin = if let Ok(parsed) = base_url.parse::<url::Url>() {
let origin = parsed.origin().ascii_serialization();
origin
.parse::<axum::http::HeaderValue>()
.unwrap_or_else(|_| panic!("invalid BASE_URL origin: {}", origin))
} else {
base_url
.parse::<axum::http::HeaderValue>()
.unwrap_or_else(|_| panic!("invalid BASE_URL: {}", base_url))
};
CorsLayer::new()
.allow_origin(allowed_origin)
.allow_methods(Any)
.allow_headers(Any)
.allow_credentials(true)
} else {
CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any)
};
// Rate limiting
let rate_limit_state = rate_limit::RateLimitState::new();
let rate_limit_cleanup = rate_limit::spawn_cleanup_task(rate_limit_state.ip_limiter.clone());
let router = Router::new()
.merge(web::web_router())
@@ -168,6 +204,10 @@ async fn main() -> Result<()> {
pool,
auth::bearer_auth_middleware,
))
.layer(axum::middleware::from_fn_with_state(
rate_limit_state.clone(),
rate_limit::rate_limit_middleware,
))
.layer(session_layer)
.layer(cors)
.with_state(app_state);
@@ -192,12 +232,28 @@ async fn main() -> Result<()> {
.context("server error")?;
session_cleanup.abort();
rate_limit_cleanup.abort();
Ok(())
}
async fn shutdown_signal() {
tokio::signal::ctrl_c()
.await
.expect("failed to install CTRL+C signal handler");
let ctrl_c = tokio::signal::ctrl_c();
#[cfg(unix)]
let terminate = async {
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
.expect("failed to install SIGTERM handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
tracing::info!("Shutting down gracefully...");
}