salvo-cors
1
总安装量
1
周安装量
#55368
全站排名
安装命令
npx skills add https://github.com/salvo-rs/salvo-skills --skill salvo-cors
Agent 安装分布
amp
1
opencode
1
cursor
1
kimi-cli
1
github-copilot
1
Skill 文档
Salvo CORS Configuration
This skill helps configure CORS and security headers in Salvo applications.
Understanding CORS
CORS (Cross-Origin Resource Sharing) is a browser security feature that restricts web pages from making requests to different domains. Without proper CORS configuration, browsers will block cross-origin requests to your API.
Setup
[dependencies]
salvo = { version = "0.89.0", features = ["cors"] }
Basic CORS Configuration
use salvo::cors::Cors;
use salvo::prelude::*;
#[tokio::main]
async fn main() {
let cors = Cors::new()
.allow_origin("https://example.com")
.allow_methods(vec!["GET", "POST", "PUT", "DELETE"])
.allow_headers(vec!["Content-Type", "Authorization"])
.into_handler();
let router = Router::new()
.hoop(cors)
.push(Router::with_path("api").get(api_handler));
let acceptor = TcpListener::new("0.0.0.0:8080").bind().await;
Server::new(acceptor).serve(router).await;
}
#[handler]
async fn api_handler() -> &'static str {
"Hello from API"
}
Allow All Origins (Development)
use salvo::cors::Cors;
// WARNING: Only use in development
let cors = Cors::new()
.allow_origin("*")
.allow_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"])
.allow_headers(vec!["*"])
.into_handler();
Production CORS Configuration
use salvo::cors::Cors;
use salvo::http::Method;
let cors = Cors::new()
// Specific allowed origins
.allow_origin(["https://app.example.com", "https://admin.example.com"])
// Allowed HTTP methods
.allow_methods(vec![Method::GET, Method::POST, Method::PUT, Method::DELETE])
// Allowed request headers
.allow_headers(vec!["Authorization", "Content-Type", "X-Requested-With"])
// Allow credentials (cookies, auth headers)
.allow_credentials(true)
// Cache preflight requests for 1 hour
.max_age(3600)
.into_handler();
Permissive CORS
Use the built-in permissive preset for quick setup:
use salvo::cors::Cors;
let cors = Cors::permissive();
let router = Router::new()
.hoop(cors)
.get(handler);
CORS with Specific Routes
Apply CORS only to API routes:
let cors = Cors::new()
.allow_origin("https://app.example.com")
.allow_methods(vec!["GET", "POST"])
.into_handler();
let router = Router::new()
.push(
Router::with_path("api")
.hoop(cors) // CORS only for /api routes
.push(Router::with_path("users").get(list_users))
.push(Router::with_path("posts").get(list_posts))
)
.push(
Router::with_path("health")
.get(health_check) // No CORS needed
);
Security Headers Middleware
Add security headers to protect against common attacks:
use salvo::prelude::*;
#[handler]
async fn security_headers(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
// Content Security Policy - prevent XSS
res.headers_mut().insert(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'".parse().unwrap()
);
// HTTP Strict Transport Security - force HTTPS
res.headers_mut().insert(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload".parse().unwrap()
);
// Prevent clickjacking
res.headers_mut().insert(
"X-Frame-Options",
"DENY".parse().unwrap()
);
// Prevent MIME type sniffing
res.headers_mut().insert(
"X-Content-Type-Options",
"nosniff".parse().unwrap()
);
// XSS Protection
res.headers_mut().insert(
"X-XSS-Protection",
"1; mode=block".parse().unwrap()
);
// Referrer Policy
res.headers_mut().insert(
"Referrer-Policy",
"strict-origin-when-cross-origin".parse().unwrap()
);
ctrl.call_next(req, depot, res).await;
}
Complete Example with CORS and Security Headers
use salvo::cors::Cors;
use salvo::http::Method;
use salvo::prelude::*;
#[handler]
async fn security_headers(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
res.headers_mut().insert("X-Content-Type-Options", "nosniff".parse().unwrap());
res.headers_mut().insert("X-Frame-Options", "DENY".parse().unwrap());
res.headers_mut().insert("X-XSS-Protection", "1; mode=block".parse().unwrap());
ctrl.call_next(req, depot, res).await;
}
#[handler]
async fn api_handler() -> Json<serde_json::Value> {
Json(serde_json::json!({"status": "ok"}))
}
#[tokio::main]
async fn main() {
// CORS configuration
let cors = Cors::new()
.allow_origin(["https://app.example.com"])
.allow_methods(vec![Method::GET, Method::POST, Method::PUT, Method::DELETE])
.allow_headers(vec!["Authorization", "Content-Type"])
.allow_credentials(true)
.max_age(86400)
.into_handler();
let router = Router::new()
.hoop(security_headers) // Apply security headers globally
.hoop(cors) // Apply CORS globally
.push(Router::with_path("api").get(api_handler));
let acceptor = TcpListener::new("0.0.0.0:8080").bind().await;
Server::new(acceptor).serve(router).await;
}
Dynamic CORS Origins
Allow origins based on request:
use salvo::cors::Cors;
use salvo::prelude::*;
fn create_cors() -> Cors {
Cors::new()
.allow_origin(|origin: &str, _req: &Request| {
// Allow any subdomain of example.com
origin.ends_with(".example.com") || origin == "https://example.com"
})
.allow_methods(vec!["GET", "POST"])
.allow_credentials(true)
}
CORS Configuration Options
| Option | Description |
|---|---|
allow_origin() |
Origins allowed to make requests |
allow_methods() |
HTTP methods allowed |
allow_headers() |
Request headers allowed |
expose_headers() |
Response headers exposed to browser |
allow_credentials() |
Allow cookies and auth headers |
max_age() |
Cache preflight response (seconds) |
Troubleshooting CORS Issues
Common Problems
- Missing OPTIONS handler: CORS preflight uses OPTIONS method
- Credentials with wildcard origin: Cannot use
*withallow_credentials(true) - Missing headers: Ensure all required headers are in
allow_headers()
Debug CORS
#[handler]
async fn cors_debug(req: &Request) {
println!("Origin: {:?}", req.header::<String>("Origin"));
println!("Method: {}", req.method());
println!("Headers: {:?}", req.headers());
}
Best Practices
- Specify exact origins in production: Avoid
*for security - Limit allowed methods: Only enable methods your API uses
- Validate headers: Only allow headers you need
- Use HTTPS: Always use HTTPS in production
- Set appropriate max_age: Balance security and performance
- Apply security headers: Add CSP, HSTS, X-Frame-Options
- Test preflight requests: Verify OPTIONS requests work correctly