bolt_web/middleware/
cors.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4
5use crate::{request::RequestBody, response::ResponseWriter, types::Middleware};
6
7pub struct CorsConfig {
8 pub allowed_origins: Vec<String>,
9 pub allow_all: bool,
10 pub allow_methods: String,
11 pub allow_headers: String,
12 pub allow_credentials: bool,
13 pub max_age: Option<u32>,
14}
15
16impl Default for CorsConfig {
17 fn default() -> Self {
18 Self {
19 allowed_origins: vec!["*".into()],
20 allow_all: true,
21 allow_methods: "GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD".into(),
22 allow_headers: "Content-Type, Authorization".into(),
23 allow_credentials: false,
24 max_age: Some(86400),
25 }
26 }
27}
28
29pub struct Cors {
30 pub config: Arc<CorsConfig>,
31}
32
33#[async_trait]
34impl Middleware for Cors {
35 async fn run(&self, req: &mut RequestBody, res: &mut ResponseWriter) {
36 let cfg = &self.config;
37
38 res.set_header("Access-Control-Allow-Methods", &cfg.allow_methods)
39 .set_header("Access-Control-Allow-Headers", &cfg.allow_headers);
40
41 if cfg.allow_all {
42 res.set_header("Access-Control-Allow-Origin", "*");
43 } else if let Some(origin) = req.get_headers("Origin") {
44 let origin_str = origin.to_str().unwrap_or("");
45 if cfg.allowed_origins.contains(&origin_str.to_string()) {
46 res.set_header("Access-Control-Allow-Origin", origin_str);
47 }
48 }
49
50 if cfg.allow_credentials {
51 res.set_header("Access-Control-Allow-Credentials", "true");
52 }
53
54 if let Some(max) = cfg.max_age {
55 res.set_header("Access-Control-Max-Age", &max.to_string());
56 }
57
58 if *req.method() == hyper::Method::OPTIONS {
59 res.status(204);
60 }
61 }
62}