This is an automated email from the ASF dual-hosted git repository.

bugraoz pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new aabb0daf4a3 Fix middleware order to prevent chunked FastAPI responses 
(#61043) (#61539)
aabb0daf4a3 is described below

commit aabb0daf4a3452f6c9ccd256208e193f881aa38a
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Fri Feb 6 20:03:10 2026 +0100

    Fix middleware order to prevent chunked FastAPI responses (#61043) (#61539)
    
    * Fix middleware order: move GZipMiddleware to end to avoid chunked 
responses
    
    * Fix middleware order and JWT/GZip setup
    
    * Fix middleware order and add final newline
    
    * test: prevent chunked encoding regression from middleware order
    
    * Move the comments to GzipMiddleware and fix the test convention
    
    ---------
    
    
    
    (cherry picked from commit bcf6749d73e076548731e335bf74e518d6cba355)
    
    Co-authored-by: abhijeets25012-tech <[email protected]>
    Co-authored-by: Abhijeet Raj Singh 
<[email protected]>
    Co-authored-by: LIU ZHE YOU <[email protected]>
---
 .../src/airflow/api_fastapi/core_api/app.py        | 11 ++++---
 .../tests/unit/api_fastapi/core_api/test_app.py    | 38 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/airflow-core/src/airflow/api_fastapi/core_api/app.py 
b/airflow-core/src/airflow/api_fastapi/core_api/app.py
index 8db1fa66680..dba358abebc 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/app.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/app.py
@@ -166,11 +166,6 @@ def init_config(app: FastAPI) -> None:
             allow_headers=allow_headers,
         )
 
-    # Compress responses greater than 1kB with optimal compression level as 5
-    # with level ranging from 1 to 9 with 1 (fastest, least compression)
-    # and 9 (slowest, most compression)
-    app.add_middleware(GZipMiddleware, minimum_size=1024, compresslevel=5)
-
     app.state.secret_key = get_signing_key("api", "secret_key")
 
 
@@ -186,6 +181,12 @@ def init_middlewares(app: FastAPI) -> None:
 
     app.add_middleware(JWTRefreshMiddleware)
 
+    # The GzipMiddleware should be the last middleware added as 
https://github.com/apache/airflow/issues/60165 points out.
+    app.add_middleware(GZipMiddleware, minimum_size=1024, compresslevel=5)
+    # Compress responses greater than 1kB with optimal compression level as 5
+    # with level ranging from 1 to 9 with 1 (fastest, least compression)
+    # and 9 (slowest, most compression)
+
 
 def init_ui_plugins(app: FastAPI) -> None:
     """Initialize UI plugins."""
diff --git a/airflow-core/tests/unit/api_fastapi/core_api/test_app.py 
b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py
new file mode 100644
index 00000000000..4881976a673
--- /dev/null
+++ b/airflow-core/tests/unit/api_fastapi/core_api/test_app.py
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import pytest
+
+from tests_common.test_utils.db import clear_db_jobs
+
+pytestmark = pytest.mark.db_test
+
+
+class TestGzipMiddleware:
+    @pytest.fixture(autouse=True)
+    def setup(self):
+        clear_db_jobs()
+        yield
+        clear_db_jobs()
+
+    def test_gzip_middleware_should_not_be_chunked(self, test_client) -> None:
+        response = test_client.get("/api/v2/monitor/health")
+        headers = {k.lower(): v for k, v in response.headers.items()}
+
+        # Ensure we do not reintroduce Transfer-Encoding: chunked
+        assert "transfer-encoding" not in headers

Reply via email to