diff --git a/nexios_contrib/etag/middleware.py b/nexios_contrib/etag/middleware.py index aad68ed..356cb5d 100644 --- a/nexios_contrib/etag/middleware.py +++ b/nexios_contrib/etag/middleware.py @@ -50,24 +50,21 @@ async def __call__( # Apply only to configured methods stream = await call_next() if request.method.upper() not in self.methods: - return None + return stream # Compute/set ETag if missing (or override when requested) has_existing = bool(response.headers.get("etag")) - print("has_existing",has_existing) if not has_existing or self.override: body = b"" async for chunk in stream.content_iterator: body += chunk compute_and_set_etag(response, body, weak=self.weak, override=True) - + print("cnext header b4 isfresh",response.headers,has_existing) # Handle If-None-Match freshness for conditional requests if is_fresh(request, response, weak_compare=True): # Per RFC 9110, a 304 response must not include a message body # Ensure body is empty; BaseResponse avoids content-length for 304 - response.make_response(BaseResponse( - status_code=304 - )) - + response.status(304) + - return None + return stream diff --git a/tests/etag/test_configuration.py b/tests/etag/test_configuration.py index e895363..63252c3 100644 --- a/tests/etag/test_configuration.py +++ b/tests/etag/test_configuration.py @@ -115,13 +115,11 @@ def test_override_configuration(self): @app1.get("/no-override") async def no_override_handler(request, response): - response.set_header("etag", '"manual-etag"') - return {"data": "test"} + return response.json({"data": "test"}).set_header("etag", '"manual-etag"') @app2.get("/with-override") async def with_override_handler(request, response): - response.set_header("etag", '"manual-etag"') - return {"data": "test"} + return response.json({"data": "test"}).set_header("etag", '"manual-etag"') client1 = TestClient(app1) client2 = TestClient(app2) @@ -146,13 +144,11 @@ def test_combined_configuration_options(self): @app.get("/get-endpoint") async def get_handler(request, response): - response.set_header("etag", '"manual-etag"') - return {"method": "GET"} + return response.json({"method": "GET"}).set_header("etag", '"manual-etag"') @app.post("/post-endpoint") async def post_handler(request, response): - response.set_header("etag", '"manual-etag"') - return {"method": "POST"} + return response.json({"method": "POST"}).set_header("etag", '"manual-etag"') client = TestClient(app) @@ -173,11 +169,11 @@ def test_case_insensitive_methods(self): @app.get("/test") async def get_handler(request, response): - return {"method": request.method} + return response.json({"method": request.method}) @app.post("/test") async def post_handler(request, response): - return {"method": request.method} + return response.json({"method": request.method}) client = TestClient(app) diff --git a/tests/etag/test_edge_cases.py b/tests/etag/test_edge_cases.py index 30bcddd..9f8bcd2 100644 --- a/tests/etag/test_edge_cases.py +++ b/tests/etag/test_edge_cases.py @@ -120,9 +120,10 @@ def test_etag_with_headers_and_cookies(self): @app.get("/headers") async def headers_handler(request, response): + response.json({"message": "Hello, World!"}) response.set_header("x-custom", "value") response.set_cookie("session", "abc123") - return {"data": "test"} + return response client = TestClient(app) diff --git a/tests/etag/test_helper_functions.py b/tests/etag/test_helper_functions.py index 97872eb..d3865a8 100644 --- a/tests/etag/test_helper_functions.py +++ b/tests/etag/test_helper_functions.py @@ -144,7 +144,7 @@ def test_set_response_etag_new(self): """Test setting ETag on response without existing ETag.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() set_response_etag(response, '"abc123"') assert response.headers.get("etag") == '"abc123"' @@ -152,7 +152,7 @@ def test_set_response_etag_override_true(self): """Test setting ETag with override=True.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"old123"') set_response_etag(response, '"new123"', override=True) assert response.headers.get("etag") == '"new123"' @@ -161,7 +161,7 @@ def test_set_response_etag_normalize(self): """Test that ETag is normalized when set.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() set_response_etag(response, "abc123") # unquoted assert response.headers.get("etag") == '"abc123"' # quoted @@ -173,7 +173,7 @@ def test_compute_and_set_etag_new(self): """Test computing and setting ETag on response without existing.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() etag = compute_and_set_etag(response, body=b"Hello, World!") assert etag.startswith('W/"') assert response.headers.get("etag") == etag @@ -182,7 +182,7 @@ def test_compute_and_set_etag_override_false(self): """Test not overriding existing ETag when override=False.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"existing"') etag = compute_and_set_etag(response, body=b"Hello, World!", override=False) assert response.headers.get("etag") == '"existing"' @@ -193,7 +193,7 @@ def test_compute_and_set_etag_override_true(self): """Test overriding existing ETag when override=True.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"existing"') etag = compute_and_set_etag(response, body=b"Hello, World!", override=True) assert response.headers.get("etag") == etag @@ -203,7 +203,7 @@ def test_compute_and_set_etag_weak_false(self): """Test computing strong ETag.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() etag = compute_and_set_etag(response, body=b"Hello, World!", weak=False) assert not etag.startswith('W/') assert response.headers.get("etag") == etag @@ -317,7 +317,7 @@ def test_is_fresh_matching_etag(self): """Test freshness when ETag matches.""" scope = create_mock_scope(headers={"if-none-match": '"abc123"'}) request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"abc123"') assert is_fresh(request, response) is True @@ -325,7 +325,7 @@ def test_is_fresh_non_matching_etag(self): """Test freshness when ETag doesn't match.""" scope = create_mock_scope(headers={"if-none-match": '"def456"'}) request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"abc123"') assert is_fresh(request, response) is False @@ -333,7 +333,7 @@ def test_is_fresh_weak_compare(self): """Test freshness with weak comparison.""" scope = create_mock_scope(headers={"if-none-match": 'W/"abc123"'}) request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"abc123"') assert is_fresh(request, response, weak_compare=True) is True @@ -341,14 +341,14 @@ def test_is_fresh_no_etag(self): """Test freshness when response has no ETag.""" scope = create_mock_scope(headers={"if-none-match": '"abc123"'}) request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() assert is_fresh(request, response) is False def test_is_fresh_no_if_none_match(self): """Test freshness when request has no If-None-Match.""" scope = create_mock_scope() request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"abc123"') assert is_fresh(request, response) is False @@ -356,6 +356,6 @@ def test_is_fresh_multiple_if_none_match(self): """Test freshness with multiple If-None-Match values.""" scope = create_mock_scope(headers={"if-none-match": '"def456", "abc123"'}) request = Request(scope, mock_receive, mock_send) - response = Response(request) + response = Response(request).empty() response.set_header("etag", '"abc123"') assert is_fresh(request, response) is True diff --git a/tests/etag/test_integration.py b/tests/etag/test_integration.py index 6044108..3b97ddb 100644 --- a/tests/etag/test_integration.py +++ b/tests/etag/test_integration.py @@ -180,8 +180,7 @@ def test_etag_override_behavior(self): @app.get("/no-override") async def handler_no_override(request, response): - response.set_header("etag", '"manual-etag"') - return {"data": "test"} + response.json({"data": "test"}).set_header("etag", '"manual-etag"') diff --git a/tests/etag/test_middleware.py b/tests/etag/test_middleware.py index c4fe655..3f1064e 100644 --- a/tests/etag/test_middleware.py +++ b/tests/etag/test_middleware.py @@ -105,8 +105,7 @@ def test_middleware_does_not_override_existing_etag(self, test_client_factory): @app.get("/test") async def handler(request, response): - response.set_header("etag", '"custom-etag"') - return {"message": "Hello, World!"} + return response.json({"message": "Hello, World!"}).set_header("etag", '"custom-etag"') with test_client_factory(app) as client: resp = client.get("/test") @@ -119,8 +118,7 @@ def test_middleware_overrides_existing_etag(self, test_client_factory): @app.get("/test") async def handler(request, response): - response.set_header("etag", '"custom-etag"') - return {"message": "Hello, World!"} + return response.json({"message": "Hello, World!"}).set_header("etag", '"custom-etag"') with test_client_factory(app) as client: resp = client.get("/test") @@ -288,8 +286,7 @@ def test_conditional_request_no_etag_on_response(self, test_client_factory): @app.get("/test") async def handler(request, response): # Manually remove any ETag that might be set - response.remove_header("etag") - return {"message": "Hello, World!"} + return response.json({"message":"hell world"}).remove_header("etag") with test_client_factory(app) as client: resp = client.get("/test", headers={"if-none-match": '"some-etag"'})