Skip to main content

rustbasic_core/middleware/
security_headers.rs

1use crate::requests::Request;
2use crate::middleware::Next;
3use crate::router::Response;
4use http::header;
5
6pub async fn security_headers_middleware(
7    req: Request,
8    next: Next,
9) -> Response {
10    let mut response = next.run(req).await;
11    
12    let headers = response.headers_mut();
13    
14    // 1. Mencegah Clickjacking
15    headers.insert(header::X_FRAME_OPTIONS, "DENY".parse().unwrap());
16    
17    // 2. Mencegah MIME Sniffing
18    headers.insert(header::X_CONTENT_TYPE_OPTIONS, "nosniff".parse().unwrap());
19    
20    // 3. XSS Protection (untuk browser lama)
21    headers.insert(header::X_XSS_PROTECTION, "1; mode=block".parse().unwrap());
22    
23    // 4. Content Security Policy (Lengkap)
24    let cfg = crate::Config::load();
25    let csp = if cfg.app_debug {
26        let port = cfg.vite_port;
27        let host = &cfg.app_host;
28        let extra_hosts = if host != "0.0.0.0" && host != "127.0.0.1" && host != "localhost" && !host.is_empty() {
29            format!("http://{}:{} ws://{}:{} ", host, port, host, port)
30        } else {
31            "".to_string()
32        };
33
34        format!(
35            "default-src 'self'; \
36             script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:{} http://127.0.0.1:{} {}https:; \
37             style-src 'self' 'unsafe-inline' http://localhost:{} http://127.0.0.1:{} {}https:; \
38             font-src 'self' https: data:; \
39             img-src 'self' data: https:; \
40             connect-src 'self' ws://localhost:{} ws://127.0.0.1:{} http://localhost:{} http://127.0.0.1:{} {}https:;",
41            port, port, extra_hosts,
42            port, port, extra_hosts,
43            port, port, port, port, extra_hosts
44        )
45    } else {
46        "default-src 'self'; \
47         script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; \
48         style-src 'self' 'unsafe-inline' https:; \
49         font-src 'self' https: data:; \
50         img-src 'self' data: https:; \
51         connect-src 'self' https:;".to_string()
52    };
53    headers.insert(header::CONTENT_SECURITY_POLICY, csp.parse().unwrap());
54    
55    response
56}