Skip to content

Change in Airflow API headers due to ordering of middleware #60165

@tirkarthi

Description

@tirkarthi

Apache Airflow version

3.1.5

If "Other Airflow 3 version" selected, which one?

No response

What happened?

We have a service that takes requests of certain url paths of Airflow API and then uses http client to hit Airflow API service and returns the response with headers back to the load balancer nginx. After upgrade from Airflow 3.1.2 to 3.1.5 we noticed the service is able to hit the Airflow API but there is a change in the header and the response type where in Airflow 3.1.2 it was not chunked and in Airflow 3.1.5 it was chunked. The chunked header is returned back to nginx which also tries to add it's own header which results in error 'upstream sent duplicate header line: "Transfer-Encoding: chunked"' . This results in nginx sending 504 response.

Upon debugging it seems that JWTRefreshMiddleware was added in #55506 with that the middleware order becomes JWTRefreshMiddleware -> GZipMiddleware. The requests go through middleware from top to bottom and the responses go through bottom to top. Looks like JWTRefreshMiddleware is added before GZipMiddleware resulting in chunked vs non-chunked response behavior change.Upon adjusting the order inairflow-core/src/airflow/api_fastapi/core_api/app.pywe were able to restore the previous behavior. As per my understandingGZipMiddlewareshould process response to compress it afterJWTRefreshMiddleware` in terms of the response cycle. There was no change in frontend and other parts but we thought to file an issue anyway.

app.add_middleware(GZipMiddleware, minimum_size=100, compresslevel=5)
app.add_middleware(JWTRefreshMiddleware)
import httpx
dict(httpx.get("http://localhost:8000/api/v2/monitor/health").headers)
{'date': 'Tue, 06 Jan 2026 13:46:29 GMT', 'server': 'uvicorn', 'content-length': '170', 
'content-type': 'application/json', 'content-encoding': 'gzip', 'vary': 'Accept-Encoding'}

Change order to have GZipMiddleware at last.

app.add_middleware(JWTRefreshMiddleware)
app.add_middleware(GZipMiddleware, minimum_size=100, compresslevel=5)
import httpx
dict(httpx.get("http://localhost:8000/api/v2/monitor/health").headers)
{'date': 'Tue, 06 Jan 2026 14:31:51 GMT', 'server': 'uvicorn', 'content-type': 'application/json', 
'content-encoding': 'gzip', 'vary': 'Accept-Encoding', 'transfer-encoding': 'chunked'}

What you think should happen instead?

No response

How to reproduce

Change order and compress size as above in airflow-core/src/airflow/api_fastapi/core_api/app.py and use httpx to analyse the change in headers.

Operating System

Ubuntu 20.04

Versions of Apache Airflow Providers

No response

Deployment

Virtualenv installation

Deployment details

No response

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions