inital
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
"""Middleware package."""
|
||||
from app.middleware.request_id import RequestIDMiddleware
|
||||
from app.middleware.security_headers import SecurityHeadersMiddleware
|
||||
from app.middleware.cors import setup_cors
|
||||
|
||||
__all__ = ["RequestIDMiddleware", "SecurityHeadersMiddleware", "setup_cors"]
|
||||
@@ -0,0 +1,29 @@
|
||||
"""CORS middleware configuration."""
|
||||
from flask import request
|
||||
|
||||
|
||||
def setup_cors(app, cors):
|
||||
"""
|
||||
Configure CORS for the application.
|
||||
|
||||
Args:
|
||||
app: Flask application instance
|
||||
cors: Flask-CORS instance
|
||||
"""
|
||||
# CORS is already initialized in extensions.py
|
||||
# This function provides additional configuration if needed
|
||||
|
||||
@app.after_request
|
||||
def after_request_cors(response):
|
||||
"""Add additional CORS headers if needed."""
|
||||
origin = request.headers.get("Origin")
|
||||
cors_origins = app.config.get("CORS_ORIGINS", [])
|
||||
|
||||
# Allow all origins in development if CORS_ORIGINS is "*"
|
||||
if cors_origins == "*" or origin in cors_origins:
|
||||
response.headers["Access-Control-Allow-Origin"] = origin if cors_origins != "*" else "*"
|
||||
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
|
||||
response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-Request-ID"
|
||||
response.headers["Access-Control-Max-Age"] = "3600"
|
||||
|
||||
return response
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Request ID middleware for request tracing."""
|
||||
import uuid
|
||||
from flask import g, request
|
||||
|
||||
|
||||
class RequestIDMiddleware:
|
||||
"""Middleware to add unique request ID to each request."""
|
||||
|
||||
def __init__(self, app=None):
|
||||
"""Initialize middleware."""
|
||||
self.app = app
|
||||
if app is not None:
|
||||
self.init_app(app)
|
||||
|
||||
def init_app(self, app):
|
||||
"""Initialize with Flask app."""
|
||||
app.before_request(self.before_request)
|
||||
app.after_request(self.after_request)
|
||||
|
||||
@staticmethod
|
||||
def before_request():
|
||||
"""Generate or extract request ID before request processing."""
|
||||
# Check if request already has an ID from client
|
||||
request_id = request.headers.get("X-Request-ID")
|
||||
|
||||
# Generate new ID if not provided
|
||||
if not request_id:
|
||||
request_id = str(uuid.uuid4())
|
||||
|
||||
# Store in Flask g object for access throughout request
|
||||
g.request_id = request_id
|
||||
|
||||
@staticmethod
|
||||
def after_request(response):
|
||||
"""Add request ID to response headers."""
|
||||
if hasattr(g, "request_id"):
|
||||
response.headers["X-Request-ID"] = g.request_id
|
||||
return response
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Security headers middleware."""
|
||||
from flask import request
|
||||
|
||||
|
||||
class SecurityHeadersMiddleware:
|
||||
"""Middleware to add security headers to responses."""
|
||||
|
||||
def __init__(self, app=None):
|
||||
"""Initialize middleware."""
|
||||
self.app = app
|
||||
if app is not None:
|
||||
self.init_app(app)
|
||||
|
||||
def init_app(self, app):
|
||||
"""Initialize with Flask app."""
|
||||
app.after_request(self.add_security_headers)
|
||||
|
||||
@staticmethod
|
||||
def add_security_headers(response):
|
||||
"""Add security headers to response."""
|
||||
# Prevent MIME type sniffing
|
||||
response.headers["X-Content-Type-Options"] = "nosniff"
|
||||
|
||||
# Enable XSS protection
|
||||
response.headers["X-XSS-Protection"] = "1; mode=block"
|
||||
|
||||
# Prevent clickjacking
|
||||
response.headers["X-Frame-Options"] = "DENY"
|
||||
|
||||
# Strict Transport Security (HSTS)
|
||||
if request.is_secure:
|
||||
response.headers["Strict-Transport-Security"] = (
|
||||
"max-age=31536000; includeSubDomains"
|
||||
)
|
||||
|
||||
# Content Security Policy
|
||||
response.headers["Content-Security-Policy"] = (
|
||||
"default-src 'self'; "
|
||||
"script-src 'self' 'unsafe-inline'; "
|
||||
"style-src 'self' 'unsafe-inline'; "
|
||||
"img-src 'self' data: https:; "
|
||||
"font-src 'self' data:; "
|
||||
"connect-src 'self'"
|
||||
)
|
||||
|
||||
# Referrer Policy
|
||||
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
|
||||
|
||||
# Permissions Policy
|
||||
response.headers["Permissions-Policy"] = (
|
||||
"geolocation=(), microphone=(), camera=()"
|
||||
)
|
||||
|
||||
return response
|
||||
Reference in New Issue
Block a user