How to configure the root_url/hostname of the API service? #7289
-
DescriptionI'm new to FastAPI and I've set up an API service with FastAPI in docker behind Traefik v2.2 proxy. Traefik is configured to use Let's Encrypt resolver to automatically deal with the SSL stuff for the hostname of this service so all the clients are talking with this API endpoint in https url e.g. https://foo.bar and the API service itself (the uvicorn server) is running in non-ssl mode. Everything works fine in normal cases. However, in certain cases, the API endpoint will send out some redirect responses. Those redirect response is targeting to http://foo.bar which is a different hostname because of the wrong scheme. I have two guesses for this:
The client receiving such a redirect response will not carry the Authorization Header by default because the hostname has changed (from https to http). Per talk with the Traefik community, the suggestion is to configure the root_url or something similar of my service (fastapi here). However I was not able find this configuration (the only relevant one I could find is talking about root_path but not root_url). Hope I could get some help here. Thank you all in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 13 comments
-
|
Just create a SERVER_HOST (or root_url) in your pydantic settings and use that to generate your redirects. |
Beta Was this translation helpful? Give feedback.
-
|
@SebastianLuebke
Thanks for your help. But some redirect response is caused by the automatic trailing slash handling of uvicorn. How should I deal with them? |
Beta Was this translation helpful? Give feedback.
-
|
The automatic response is a relative redirect i think. so this should just work. enable http to https rewrite in your proxy config i use nginx for that |
Beta Was this translation helpful? Give feedback.
-
|
@SebastianLuebke Thanks for your response. But I don't understand the second half. If the request is proxyed to http uvicorn server,shouldn't the request become http again? My current setup is similar to yours, all http requests to my traefik proxy is redirected to be https, but the traefik router itself is talking without ssl to my server and cause the request the server received to be http. And thus the redirect response is http. |
Beta Was this translation helpful? Give feedback.
-
|
That doesnt matter in this setup. even if the client gets a http redirect response from your uvicorn server, traefik will convert it to a https request or the browser does it for you if you use HTTP Strict Transport Security.
|
Beta Was this translation helpful? Give feedback.
-
|
@SebastianLuebke Thanks for your comprehensive explanation. I understand what you are saying there. But the problem is: my client is sending request to traefik https in the first step, as I mentioned in the post. That's why there would be a hostname change and the authorization header will be dropped. I guess in most cases, we don't want to set the destination url from client to be http if https is possible, though I know let the clients to talk with http instead of https would immediately resolve the problem as you said there. Is it possible to leave clients talking with https through router, but fastapi still response with redirect to https? |
Beta Was this translation helpful? Give feedback.
-
|
Try starting uvicorn with the --proxy-headers parameter and add the X-Forwarded-For and X-Forwarded-Proto header in traefik |
Beta Was this translation helpful? Give feedback.
-
Thank you for your help! I'm currently trying to configure traefik but not yet succeed. In the meanwhile, would you mind clarify a little bit how this would affect the above communication steps and realize the aim? I did a quick search for these headers, and it seems they are designed to record the scheme and client ip in between the client and proxy/load-balancer. And run uvicorn with But how would that affect the redirect response? Shouldn't it still put a http location there as the request it received from the proxy is http? Feel free to clarify me if I have any misunderstanding. |
Beta Was this translation helpful? Give feedback.
-
|
afaik starlette honors the x-forwareded-proto header and will send redirect responses according to it. |
Beta Was this translation helpful? Give feedback.
-
|
uvicorn handles trailing slash redirects by default, you can disable this by passing Given your proxy is communicating with
The easiest approach is to ensure the In the case of Traefik, you can enable One issue I personally had using Docker was passing the proxy IP to One solution to this would be setting Alternatively, you can add the from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
...
proxy_ip = socket.gethostbyname("proxy-container-name")
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=proxy_ip) |
Beta Was this translation helpful? Give feedback.
-
These two rules worked for me when working with traefikv2 https. Along with for communicating via docker hosts
|
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the help here everyone! 👏 🙇 If that solves the original problem, then you can close this issue @Reapor-Yurnero ✔️
|
Beta Was this translation helpful? Give feedback.
-
|
Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs. |
Beta Was this translation helpful? Give feedback.
@Reapor-Yurnero
uvicorn handles trailing slash redirects by default, you can disable this by passing
redirect_slashes=Falseto yourAPIRouter.Given your proxy is communicating with
uvicornvia HTTP, it will naturally redirect to the same scheme (http). As @SebastianLuebke mentioned,uvicorn* does honor theX-FORWARDED-PROTOif enabled. It is enabled by default, and will only populate this information for trusted clients, which are supplied touvicornvia the command line, or an environment variable: