sanic-org/sanic

Use reverse proxy headers (x-forwarded-proto, x-forwarded-path, ...) in url_for construction

Open

#2,471 opened on May 26, 2022

 (5 comments) (0 reactions) (0 assignees)Python (1,515 forks)batch import
feature requesthelp wanted

Repository metrics

Stars
 (17,623 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Is your feature request related to a problem? Please describe. I'm running Sanic behind an nginx reverse proxy, mounted to a subdirectory. I want app.url_for(_external=True) to return correct absolute URLs. In my own code I have a helper function for that, but extensions (like the openapi code in sanic-ext) don't know about them.

Describe the solution you'd like The current documentation regarding proxy headers (https://github.com/sanic-org/sanic-guide/blob/927cebaf33394481810f0c50dac15898edd4ed67/src/en/guide/advanced/proxy-headers.md?plain=1#L48) suggests that the headers x-forwarded-proto, x-forwarded-host, x-forwarded-port, x-forwarded-path, and x-scheme could be used for URL construction.

Example: Suppose I have a route like

@app.route("/hi")
async def hello(request):
    return html('<a href="' + app.url_for('hello', _external=True) + '">here</a>')

I have app.config.REAL_IP_HEADER = 'X-Real-IP' and a request comes in as

GET /hi HTTP/1.0
X-Real-IP: 198.51.100.23
X-Forwarded-Host: example.com
X-Forwarded-Path: /api
X-Forwarded-Proto: https

I want it to return <a href="https://example.com/api/hi">here</a>

Additional context There is a slight problem here in that url_for() doesn't receive the request object. For reference, django-rest-api for example solves this by always passing in the request into Serializers (which might call reverse()). But even adding a _request doesn't solve the problem of existing naive code that's calling url_for() with no request object (and might not even have a request object reference).

Is there some sort of context variable for "the current request", like in Flask?

Contributor guide