uvicorn icon indicating copy to clipboard operation
uvicorn copied to clipboard

Support X-Forwarded-Host in proxy-headers

Open retrry opened this issue 4 years ago • 10 comments

Checklist

  • [x] There are no similar issues or pull requests for this yet.
  • [ ] I discussed this idea on the community chat and feedback is positive.

Is your feature related to a problem? Please describe.

When using uvicorn, with starlette URLs with url_for are generated with bad host, when application is behind proxy and proxy sets original host to X-Forwarded-Host.

https://github.com/encode/starlette/issues/604

Describe the solution you would like.

Currently uvicorn uses only X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate scope with remote information. But there is X-Forwarded-Host header, which should be used for populating server information in scope.

retrry avatar Feb 24 '21 09:02 retrry

would you mind setting a clear example of what the issue is, it's been a while since I haven't touched this, there is also an old PR on proxy headers so not sure this doesn't address this, will try to find it later

euri10 avatar Feb 25 '21 07:02 euri10

closing as stale, feel free to reopen

euri10 avatar May 27 '21 13:05 euri10

@euri10 I would like to expand on the issue here.

A use-case example would be the redirect_slashes feature in starlette.routing.Router (used in fastapi.APIRouter).

When a route is defined as /this/path/ and I make a request to /this/path (missing the trailing check), I will get a redirect to the other route.

This redirect is an absolute URL, not relative, so it includes the Hostname. To build that URL, starlette uses the Host header to find the hostname.

But, in the case of Heroku apps, many CDN setups etc there is a reverse proxy in front of the app. the proxy rewrite the request, puts your webservice into the Host header, and moves the client-side hostname used into the X-Forwarded-For header.

I imagine that ProxyHeadersMiddleware could do a similar swap as with forwarded-proto & forwarded-for, so the forwarded-host is put into the standard host header, so all apps can work with this.

Of course I could also imagine adapting starlette.datastructures.url, not sure what's the best place?

syphar avatar Oct 16 '25 09:10 syphar

hi @syphar I dont maintain uvicorn anymore nor use it anymore, there are alternatives on pretty much all encode projects you may want to consider ;)

euri10 avatar Oct 16 '25 10:10 euri10

hi @syphar I dont maintain uvicorn anymore nor use it anymore, there are alternatives on pretty much all encode projects you may want to consider ;)

In case you want to provide more info, I don't mind you being more open. I think @euri10 meant (sorry if wrong):

Starlette/FastAPI > Litestar Uvicorn > Granian

What about httpx? aiohttp?

Kludex avatar Oct 16 '25 10:10 Kludex

Starlette/FastAPI > Litestar Uvicorn > Granian

:) that's what I'm currently using but you can find many more on https://github.com/florimondmanca/awesome-asgi?tab=readme-ov-file#servers

What about httpx? aiohttp?

still in love httpx, with an aiohttp transport though, but recently https://github.com/MarkusSintonen/pyreqwest popped so that may be an interesting one, idk I never tested.

to be back on topic I would deal with proxy headers at the reverse proxy level and not the webserver, this makes more sense to me but ymmv

euri10 avatar Oct 16 '25 11:10 euri10

thank you for all your responses!

Do understand correctly that uvicorn is unmaintained then? And we should switch?

syphar avatar Oct 16 '25 11:10 syphar

No, I'm maintaining it.

Kludex avatar Oct 16 '25 11:10 Kludex

ah, that's good to hear, sorry vor the misunderstanding.

Do you see a use for the X-Forwarded-Host handling? Would you accept a PR?

Or do you see this somewhere else?

(edit: wrong header name)

syphar avatar Oct 16 '25 12:10 syphar

yes, PR welcome.

For reference: https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/.

Kludex avatar Oct 17 '25 10:10 Kludex