# Headers

Request and response headers are available in the Request and HTTPResponse objects, respectively. They make use of the multidict package (opens new window) that allows a single key to have multiple values.

FYI

Header keys are converted to lowercase when parsed. Capitalization is not considered for headers.

# Request

Sanic does attempt to do some normalization on request headers before presenting them to the developer, and also make some potentially meaningful extractions for common use cases.

# Tokens

Authorization tokens in the form Token <token> or Bearer <token> are extracted to the request object: request.token.

@app.route("/")
async def handler(request):
    return text(request.token)
$ curl localhost:8000 \
    -H "Authorization: Token ABCDEF12345679"
ABCDEF12345679
$ curl localhost:8000 \
    -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

# Proxy headers

Sanic has special handling for proxy headers. See the proxy headers section for more details.

# Request ID

NEW

New in v21.3, often it is convenient or necessary to track a request by its X-Request-ID header. You can easily access that as: request.id.

@app.route("/")
async def handler(request):
    return text(request.id)
$ curl localhost:8000 \
    -H "X-Request-ID: ABCDEF12345679"
ABCDEF12345679

# Response

Sanic will automatically set the following response headers (when appropriate) for you:

  • content-length
  • content-type
  • connection
  • transfer-encoding
  • Any other header that you would like to set can be done either in the route handler, or a response middleware.

    @app.route("/")
    async def handler(request):
        return text("Done.", headers={"content-language": "en-US"})
    @app.middleware("response")
    async def add_csp(request, response):
        response.headers["content-security-policy"] = "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';base-uri 'self';form-action 'self'"
    

Any other header that you would like to set can be done either in the route handler, or a response middleware.

@app.route("/")
async def handler(request):
    return text("Done.", headers={"content-language": "en-US"})
@app.middleware("response")
async def add_csp(request, response):
    response.headers["content-security-policy"] = "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';base-uri 'self';form-action 'self'"

NEW

A common middleware you might want is to add a X-Request-ID header to every response. As stated above: request.id will provide the ID from the incoming request. But, even if no ID was supplied in the request headers, one will be automatically supplied for you.

See API docs for more details (opens new window)

@app.route("/")
async def handler(request):
    return text(str(request.id))
@app.on_response
async def add_request_id_header(request, response):
    response.headers["X-Request-ID"] = request.id
$ curl localhost:8000 -i
HTTP/1.1 200 OK
X-Request-ID: 805a958e-9906-4e7a-8fe0-cbe83590431b
content-length: 36
connection: keep-alive
content-type: text/plain; charset=utf-8
805a958e-9906-4e7a-8fe0-cbe83590431b
MIT Licensed
Copyright © 2018-present Sanic Community Organization

~ Made with ❤️ and ☕️ ~