I'd like to know the following
request.url
be manipulated on the NGINX level -- setting proxy headers doesn't modify it at all?request.url
be manipulated via a Starlette Middleware -- somehow what I did doesn't have any effect?The setting is like this:
I have a FastAPI app running behind a NGINX proxy. Via the browser, I send requests to NGINX via HTTPS (https://www.example.com
) , but whatever I do, request.url
on Starlette's side is always http://www.example.com
.
I made a small FastAPI endpoint for demonstration purposes
@app.get("/test")
def some_test(request: Request):
return {"request.url": request.url,
"request['headers']": request["headers"],
"request.client": request.client}
and in the following screenshots I show what I get (domain is anonymized; set to xyz
):
https://www.example.com/test
https://www.example.com/test
Request.url
, it says http://www.example.com/test
Is this behaviour how it should be? In the screenshot I also print the host
and x-forwarded-proto
and x-forwarded-schema
which I set the NGINX config to HTTPS, but the object Request
isn't modified at all by that.
What can I do to correct this on the NGINX or FastAPI/Starlette level?
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Scheme $scheme;
with no success at all.from fastapi import Request
from starlette.datastructures import URL
@app.middleware("http")
async def some_middlware(request: Request, call_next):
if "/test" in str(request.url):
print(f"before {request.url}")
request._url = URL(str(request.url).replace("http", "https"))
print(f"after {request.url}")
response = await call_next(request)
return response
but this also doesn't modify the request.url
shown in the response.Now the proxying of the schema works.
The problem was,the following:
Before my Dockerfile looked like
ENTRYPOINT ["uvicorn", "main:app", "--proxy-headers", "--forwarded-allow-ips='*'", "--host", "0.0.0.0"]
The quotation marks in the --forwarded-allow-ips
parameter do not work. Instead the entrypoint should read
ENTRYPOINT ["uvicorn", "main:app", "--proxy-headers", "--forwarded-allow-ips=*", "--host", "0.0.0.0"]
Hint: To be a bit cleaner, one should not allow *
as an IP address, instead you should specify the IP address.