在 Cargo.toml 補上:
tower-http = { version = "0.6", features = ["cors", "trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
http = "1.3"
在 main.rs 新增的 imports 與中間件設定:
新增 imports(在檔案頂端):
use tower_http::cors::{CorsLayer, Any, AllowOrigin};
use tower_http::trace::{TraceLayer, DefaultMakeSpan, DefaultOnResponse};
use tracing_subscriber::{EnvFilter, fmt};
use tracing::Level;
use http::{Method, HeaderValue};
use tracing_subscriber::prelude::*;
在 main 加入 tracing 初始化(放在 dotenv().ok() 之後):
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::registry()
    .with(env_filter)
    .with(fmt::layer().with_target(false)) // 或 .json() 輸出 JSON
    .init();
建立 CorsLayer 與 TraceLayer:
let localhost = HeaderValue::from_static("http://localhost:5173");
	
	let cors = CorsLayer::new()
		.allow_origin(AllowOrigin::exact(localhost))
		.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE, Method::OPTIONS])
		.allow_headers(Any)
		.max_age(std::time::Duration::from_secs(600));
let trace = TraceLayer::new_for_http()
    .make_span_with(DefaultMakeSpan::new().include_headers(false)) // 不自動包含 headers,避免敏感資訊
    .on_response(DefaultOnResponse::new().level(Level::INFO));
把 layer 套到 Router:
let app = Router::new()
    // ...
    .layer(trace)
    .layer(cors)
    .layer(Extension(pool))
    .layer(Extension(redis_conn));
備註
在 .env 加入:
RUST_LOG=debug
開啟詳細DEBUG紀錄
OPTIONS http://127.0.0.1:3000/users
 HTTP/1.1 200 OK
 vary: origin, access-control-request-method, access-control-request-headers
 access-control-allow-methods: GET,POST,PUT,DELETE,OPTIONS
 access-control-allow-headers: *
 access-control-max-age: 600
 access-control-allow-origin: http://localhost:5173
 allow: POST,GET,HEAD
 content-length: 0
 date: Sun, 05 Oct 2025 00:56:25 GMT
檢查回應是否有 Access-Control-Allow-Origin / Allow-Methods
重點結論