secure.py
supports several popular Python web frameworks. Below are examples showing how to set the default security headers in each framework, along with a brief introduction and links to each project. Additionally, we provide guidance for integrating Secure Headers with custom or unsupported frameworks.
- aiohttp
- Bottle
- CherryPy
- Django
- Falcon
- FastAPI
- Flask
- Masonite
- Morepath
- Pyramid
- Quart
- Responder
- Sanic
- Starlette
- Tornado
- TurboGears
- Web2py
- Custom Frameworks
If you're using Uvicorn as the ASGI server (commonly used with frameworks like FastAPI, Starlette, and others), Uvicorn automatically injects a Server: uvicorn
header into all HTTP responses by default. This can lead to multiple Server
headers when using Secure.py
to set a custom Server
header.
To prevent Uvicorn from adding its default Server
header, you can disable it by passing the --no-server-header
option when running Uvicorn, or by setting server_header=False
in the uvicorn.run()
method:
import uvicorn
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
server_header=False, # Disable Uvicorn's default Server header
)
If you're using Uvicorn via Gunicorn (e.g., with the UvicornWorker
), note that this setting is not passed through automatically. In such cases, you may need to subclass the worker to fully override the Server
header.
For more information, refer to the Uvicorn Settings.
aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. It's designed for building efficient web applications with asynchronous capabilities.
from aiohttp import web
from secure import Secure
secure_headers = Secure.with_default_headers()
@web.middleware
async def add_security_headers(request, handler):
response = await handler(request)
await secure_headers.set_headers_async(response)
return response
app = web.Application(middlewares=[add_security_headers])
app.router.add_get("/", lambda request: web.Response(text="Hello, world"))
web.run_app(app)
from aiohttp import web
from secure import Secure
secure_headers = Secure.with_default_headers()
async def handle(request):
response = web.Response(text="Hello, world")
await secure_headers.set_headers_async(response)
return response
app = web.Application()
app.router.add_get("/", handle)
web.run_app(app)
Bottle is a fast, simple, and lightweight WSGI micro web-framework for Python. It's perfect for small applications and rapid prototyping.
from bottle import Bottle, response, run
from secure import Secure
secure_headers = Secure.with_default_headers()
app = Bottle()
@app.hook("after_request")
def add_security_headers():
secure_headers.set_headers(response)
run(app, host="localhost", port=8080)
from bottle import Bottle, response, run
from secure import Secure
secure_headers = Secure.with_default_headers()
app = Bottle()
@app.route("/")
def index():
secure_headers.set_headers(response)
return "Hello, world"
run(app, host="localhost", port=8080)
CherryPy is a minimalist, object-oriented web framework that allows developers to build web applications in a way similar to building other Python applications.
import cherrypy
from secure import Secure
secure_headers = Secure.with_default_headers()
class HelloWorld:
@cherrypy.expose
def index(self):
cherrypy.response.headers.update(secure_headers.headers)
return b"Hello, world"
config = {
"/": {
"tools.response_headers.on": True,
"tools.response_headers.headers": secure_headers.headers
}
}
cherrypy.quickstart(HelloWorld(), "/", config)
import cherrypy
from secure import Secure
secure_headers = Secure.with_default_headers()
class HelloWorld:
@cherrypy.expose
def index(self):
cherrypy.response.headers.update(secure_headers.headers)
return b"Hello, world"
cherrypy.quickstart(HelloWorld())
Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design.
from django.http import HttpResponse
from secure import Secure
secure_headers = Secure.with_default_headers()
def set_secure_headers(get_response):
def middleware(request):
response = get_response(request)
secure_headers.set_headers(response)
return response
return middleware
from django.http import HttpResponse
from secure import Secure
secure_headers = Secure.with_default_headers()
def home(request):
response = HttpResponse("Hello, world")
secure_headers.set_headers(response)
return response
Falcon is a minimalist WSGI library for building speedy web APIs and app backends.
import falcon
from secure import Secure
secure_headers = Secure.with_default_headers()
class SecureMiddleware:
def process_response(self, req, resp, resource, req_succeeded):
secure_headers.set_headers(resp)
app = falcon.App(middleware=[SecureMiddleware()])
class HelloWorldResource:
def on_get(self, req, resp):
resp.text = "Hello, world"
app.add_route("/", HelloWorldResource())
import falcon
from secure import Secure
secure_headers = Secure.with_default_headers()
class HelloWorldResource:
def on_get(self, req, resp):
resp.text = "Hello, world"
secure_headers.set_headers(resp)
app = falcon.App()
app.add_route("/", HelloWorldResource())
FastAPI is a modern, fast web framework for building APIs with Python 3.6+.
from fastapi import FastAPI
from secure import Secure
app = FastAPI()
secure_headers = Secure.with_default_headers()
@app.middleware("http")
async def add_security_headers(request, call_next):
response = await call_next(request)
await secure_headers.set_headers_async(response)
return response
from fastapi import FastAPI, Response
from secure import Secure
app = FastAPI()
secure_headers = Secure.with_default_headers()
@app.get("/")
def read_root(response: Response):
secure_headers.set_headers(response)
return {"Hello": "World"}
Flask is a lightweight WSGI web application framework.
from flask import Flask, Response
from secure import Secure
app = Flask(__name__)
secure_headers = Secure.with_default_headers()
@app.after_request
def add_security_headers(response: Response):
secure_headers.set_headers(response)
return response
from flask import Flask, Response
from secure import Secure
app = Flask(__name__)
secure_headers = Secure.with_default_headers()
@app.route("/")
def home():
response = Response("Hello, world")
secure_headers.set_headers(response)
return response
Masonite is a modern and developer-friendly Python web framework.
from masonite.foundation import Application
from masonite.response import Response
from secure import Secure
app = Application()
secure_headers = Secure.with_default_headers()
def add_security_headers(response: Response):
secure_headers.set_headers(response)
return response
from masonite.request import Request
from masonite.response import Response
from masonite.foundation import Application
from secure import Secure
app = Application()
secure_headers = Secure.with_default_headers()
@app.route("/")
def home(request: Request, response: Response):
return add_security_headers(response.view("Hello, world"))
Morepath is a Python web framework that provides URL to object mapping.
Morepath doesn’t have middleware. Use per-view settings as shown in the single route example.
import morepath
from secure import Secure
secure_headers = Secure.with_default_headers()
class App(morepath.App):
pass
@App.path(path="")
class Root:
pass
@App.view(model=Root)
def hello_world(self, request):
response = morepath.Response("Hello, world")
secure_headers.set_headers(response)
return response
morepath.run(App())
Pyramid is a small, fast Python web framework.
from pyramid.config import Configurator
from pyramid.response import Response
from secure import Secure
secure_headers = Secure.with_default_headers()
def add_security_headers(handler, registry):
def tween(request):
response = handler(request)
secure_headers.set_headers(response)
return response
return tween
from pyramid.config import Configurator
from pyramid.response import Response
from secure import Secure
secure_headers = Secure.with_default_headers()
def hello_world(request):
response = Response("Hello, world")
secure_headers.set_headers(response)
return response
Quart is an async Python web framework.
from quart import Quart, Response
from secure import Secure
app = Quart(__name__)
secure_headers = Secure.with_default_headers()
@app.after_request
async def add_security_headers(response: Response):
await secure_headers.set_headers_async(response)
return response
from quart import Quart, Response
from secure import Secure
app = Quart(__name__)
secure_headers = Secure.with_default_headers()
@app.route("/")
async def index():
response = Response("Hello, world")
await secure_headers.set_headers_async(response)
return response
Responder is a fast web framework for building APIs.
import responder
from secure import Secure
api = responder.API()
secure_headers = Secure.with_default_headers()
@api.route("/")
async def add_security_headers(req, resp):
await secure_headers.set_headers_async(resp)
import responder
from secure import Secure
api = responder.API()
secure_headers = Secure.with_default_headers()
@api.route("/")
async def home(req, resp):
resp.text = "Hello, world"
await secure_headers.set_headers_async(resp)
Sanic is a Python web framework written for fast performance.
from sanic import Sanic, response
from secure import Secure
app = Sanic("SecureApp")
secure_headers = Secure.with_default_headers()
@app.middleware("response")
async def add_security_headers(request, resp):
secure_headers.set_headers(resp)
from sanic import Sanic, response
from secure import Secure
app = Sanic("SecureApp")
secure_headers = Secure.with_default_headers()
@app.route("/")
async def index(request):
resp = response.text("Hello, world")
secure_headers.set_headers(resp)
return resp
Starlette is a lightweight ASGI framework.
from starlette.applications import Starlette
from starlette.responses import Response
from starlette.middleware.base import BaseHTTPMiddleware
from secure import Secure
secure_headers = Secure.with_default_headers()
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
await secure_headers.set_headers_async(response)
return response
from starlette.applications import Starlette
from starlette.responses import Response
from secure import Secure
secure_headers = Secure.with_default_headers()
async def homepage(request):
response = Response("Hello, world")
await secure_headers.set_headers_async(response)
return response
Tornado is a Python web framework designed for asynchronous networking.
Tornado doesn't directly support middleware, but you can use it in each request handler as shown in the single route example.
import tornado.ioloop
import tornado.web
from secure import Secure
secure_headers = Secure.with_default_headers()
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
secure_headers.set_headers(self)
TurboGears is a full-stack framework.
from tg import AppConfig, Response, TGController, expose
from secure import Secure
secure_headers = Secure.with_default_headers()
class SecureMiddleware:
def __init__(self, req, resp):
secure_headers.set_headers(resp)
config = AppConfig(minimal=True, root_controller=TGController)
config["middleware"] = [SecureMiddleware]
from tg import AppConfig, Response, TGController, expose
from secure import Secure
secure_headers = Secure.with_default_headers()
class RootController(TGController):
@expose()
def index(self):
response = Response("Hello, world")
secure_headers.set_headers(response)
return response
Web2py is a free web framework designed for rapid development of database-driven applications.
Web2py doesn't directly support middleware, but you can use it in each route.
from gluon import current
from secure import Secure
secure_headers = Secure.with_default_headers()
def index():
secure_headers.set_headers(current.response)
return "Hello, world"
If you are using a framework that is not listed here, secure.py
can still be integrated. Most frameworks offer a way to manipulate response headers, which is all you need to apply security headers.
-
Identify the Response Object: Each framework typically has a response object or an equivalent that allows you to modify HTTP headers.
-
Set Headers: Use the
set_headers()
orset_headers_async()
method to inject security headers into the response before sending it back to the client. -
Asynchronous Support: For asynchronous frameworks, ensure that you're calling the correct async version of methods.
from secure import Secure
secure_headers = Secure().with_default_headers()
def add_secure_headers(response):
secure_headers.set_headers(response)
return response
# Apply the `add_secure_headers` function wherever your framework handles responses.
If you encounter any issues integrating Secure Headers with your custom framework, feel free to open an issue on our GitHub repository or consult the framework's documentation for handling response headers.