I wrapped my FastAPI app according to the docs:
fast_app = FastAPI(...)
# add routers, mounts, other middlewares...
# The final middleware is ProxyFixMiddleware
app = ProxyFixMiddleware(fast_app, mode='legacy')
# app is targeted by the hypercorn cli or started via trio when the module is executed
(The docs should probably make it clear it must be done this way: I lost almost two hours wondering why it wasn't doing anything with FastAPI.add_middleware before coming across #179)
I have a view function:
@router.get(
"/signin",
status_code=HTTPStatus.TEMPORARY_REDIRECT,
)
async def sign_in(req: Request):
logger.debug(req.scope)
async with AsyncOAuth2Client(
b.config.OAUTH["client_id"],
redirect_uri=str(req.url_for(authorize.__name__)),
scope=["openid", "email", "profile"],
**b.config.OAUTH["httpxkw"],
) as client:
uri, state = client.create_authorization_url(
str(b.config.OAUTH["authorization_endpoint"])
)
return RedirectResponse(uri)
My NGINX location block has these settings:
proxy_pass http://unix:/run/hypercorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
The problem started with req.url_for: it keeps rendering a URL with http:// and breaking OAuth.
Hypercorn correctly logs that X-Forwarded-Proto is https. However, when I log req.scope within the app, pretty much everything I expected the middleware to fix is set as if the middleware weren't present at all:
{
'type': 'http',
'http_version': '1.1',
'asgi': {'spec_version': '2.1', 'version': '3.0'},
'method': 'GET',
'scheme': 'http', # WRONG
...,
'client': None, # WRONG -- should equal X-Forwarded-For
'server': None,
'headers': [
(b'host', b'<server_name in nginx and hypercorn.toml>), # Correct
(b'x-forwarded-proto', b'https'),
(b'x-forwarded-for', b'<my ip>'), ...
],
...
}
So Hypercorn itself clearly sees the proxy headers and is consuming them itself more or less correctly, but it's not adding that information to the Scope in a way that Starlette can see it.
I hope this is just my error, because that would be easy to fix. Maybe I need to wrap the Router instead of the FastAPI? Or maybe it should be the first instead of the last middleware?
I wrapped my
FastAPIapp according to the docs:(The docs should probably make it clear it must be done this way: I lost almost two hours wondering why it wasn't doing anything with
FastAPI.add_middlewarebefore coming across #179)I have a view function:
My NGINX
locationblock has these settings:The problem started with
req.url_for: it keeps rendering a URL withhttp://and breaking OAuth.Hypercorn correctly logs that
X-Forwarded-Protois https. However, when I logreq.scopewithin the app, pretty much everything I expected the middleware to fix is set as if the middleware weren't present at all:So Hypercorn itself clearly sees the proxy headers and is consuming them itself more or less correctly, but it's not adding that information to the Scope in a way that Starlette can see it.
I hope this is just my error, because that would be easy to fix. Maybe I need to wrap the
Routerinstead of theFastAPI? Or maybe it should be the first instead of the last middleware?