[Python] How do I make FastAPI URLs include the proxied URL?

Discussão em 'Python' iniciado por Stack, Fevereiro 19, 2025.

  1. Stack

    Stack Membro Participativo

    I have a FastAPI application that is behind a NextJS reverse proxy. I'm using NextJS rewrites, which sets the x-forwarded-for header to the externally-visible hostname and port. The rewrite looks like this:

    rewrites: async () => [
    {
    source: "/api/:slug*",
    destination: "http://backend:8000/:slug*"
    }
    ]


    The whole lot is running in a docker stack (which is where hostnames like backend come from) and I end up with headers like this:

    host: backend:8000
    x-forwarded-host: localhost:3000


    I'm then emailing a link from the FastAPI application. I construct the URL like this:

    @app.get("/verify")
    async def verify(token: str):
    ...

    @app.post("/signup")
    async def signup(body: SignupRequest, request: Request) -> str:
    user = add_user(body.username, body.email)
    token = user.get_signup_token()
    url = request.url_for("verify").include_query_params(token=token)
    email_verification(body.email, url)
    return ""


    I've set up FastAPI with root_path="/api" so that the path is rewritten correctly.

    The resulting url is http://backend:8000/api/verify. I want it to be http://localhost:3000/api/verify (ie to have the actual hosted URL rather than the intra-docker-stack URL).

    I've tried adding a middleware like this:

    @app.middleware("http")
    async def rewrite_host_header(request: Request, call_next):
    if "x-forwarded-host" in request.headers:
    request.headers["host"] = request.headers["x-forwarded-host"]
    return await call_next(request)


    but this doesn't seem to make a difference. I've also tried adding request.url = request.url.replace(host=request.headers["x-forwarded-for"]) but this also doesn't change the output of request.url_for(...).

    How am I meant to configure this so that URLs are emitted with the right scheme, hostname and port?

    Edit to add: I've tried also setting X-Forwarded-Proto, X-Forwarded-Port, X-Forwarded-Prefix and X-Forwarded-For, making requests directly to FastAPI using curl and so cutting out the NextJS step. None of it makes any difference to the URLs that url_for() emits.

    Continue reading...

Compartilhe esta Página