Use reverse proxy headers (x-forwarded-proto, x-forwarded-path, ...) in url_for construction
#2,471 opened on May 26, 2022
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?