File size: 1,946 Bytes
22b729d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from __future__ import annotations
from typing import Any
from app.core.config import Settings

class SecurityHeadersMiddleware:
    def __init__(self, app: Any, settings: Settings) -> None:
        self.app=app; self.settings=settings
    async def __call__(self, scope: dict[str, Any], receive: Any, send: Any) -> None:
        if scope.get('type')!='http':
            await self.app(scope, receive, send); return
        async def send_wrapper(message: dict[str, Any]) -> None:
            if message.get('type')=='http.response.start':
                headers=message.setdefault('headers', [])
                self._append(headers, 'x-content-type-options', 'nosniff')
                # X-Frame-Options can't allow-list an origin; leave it unset (X_FRAME_OPTIONS="")
                # when the app must be embeddable (e.g. the Hugging Face Space iframe) and rely
                # on the CSP frame-ancestors directive instead.
                if self.settings.x_frame_options:
                    self._append(headers, 'x-frame-options', self.settings.x_frame_options)
                self._append(headers, 'referrer-policy', 'no-referrer')
                self._append(headers, 'permissions-policy', 'camera=(), microphone=(), geolocation=()')
                self._append(headers, 'cross-origin-opener-policy', 'same-origin')
                self._append(headers, 'content-security-policy', self.settings.content_security_policy)
                if self.settings.enable_hsts:
                    self._append(headers, 'strict-transport-security', f'max-age={self.settings.hsts_max_age_seconds}; includeSubDomains')
            await send(message)
        await self.app(scope, receive, send_wrapper)
    @staticmethod
    def _append(headers: list[tuple[bytes, bytes]], name: str, value: str) -> None:
        key=name.encode('latin-1')
        if not any(k.lower()==key for k,_ in headers): headers.append((key, value.encode('latin-1')))