From e69c22f7ca8591cd550cb336e6d6fccc1058a3a7 Mon Sep 17 00:00:00 2001 From: Phungtheanh Date: Wed, 13 May 2026 23:41:32 +0700 Subject: [PATCH] @ Fix: Handle invalid HTTP status codes properly Previously, http_status_to_exit_status() would return SUCCESS for invalid status codes (< 100 or >= 600), which is incorrect behavior. This fix ensures: - Status codes 100-199 (Informational) return SUCCESS - Status codes 200-299 (Success) return SUCCESS - Status codes 300-399 return ERROR_HTTP_3XX (unless follow=True) - Status codes 400-499 return ERROR_HTTP_4XX - Status codes 500-599 return ERROR_HTTP_5XX - Invalid codes (< 100 or >= 600) now return ERROR instead of SUCCESS Added comprehensive test coverage for edge cases including informational responses and invalid status codes. @ --- httpie/status.py | 14 ++++++- tests/test_status_edge_cases.py | 70 +++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 tests/test_status_edge_cases.py diff --git a/httpie/status.py b/httpie/status.py index 2abf291843..e14124fa55 100644 --- a/httpie/status.py +++ b/httpie/status.py @@ -28,13 +28,23 @@ def http_status_to_exit_status(http_status: int, follow=False) -> ExitStatus: """ if 300 <= http_status <= 399 and not follow: - # Redirect + # Redirect without follow return ExitStatus.ERROR_HTTP_3XX + elif 300 <= http_status <= 399 and follow: + # Redirect with follow - treat as success + return ExitStatus.SUCCESS elif 400 <= http_status <= 499: # Client Error return ExitStatus.ERROR_HTTP_4XX elif 500 <= http_status <= 599: # Server Error return ExitStatus.ERROR_HTTP_5XX - else: + elif 200 <= http_status <= 299: + # Success return ExitStatus.SUCCESS + elif 100 <= http_status <= 199: + # Informational - treat as success + return ExitStatus.SUCCESS + else: + # Invalid or unknown status codes (< 100, >= 600) + return ExitStatus.ERROR diff --git a/tests/test_status_edge_cases.py b/tests/test_status_edge_cases.py new file mode 100644 index 0000000000..f09a0d5f80 --- /dev/null +++ b/tests/test_status_edge_cases.py @@ -0,0 +1,70 @@ +"""Test edge cases for HTTP status code handling.""" +import pytest +from httpie.status import ExitStatus, http_status_to_exit_status + + +def test_informational_status_codes(): + """Test that 1xx status codes are handled correctly.""" + # 1xx Informational responses should return SUCCESS for 2xx-like behavior + # or could be considered as SUCCESS since they're not errors + assert http_status_to_exit_status(100) == ExitStatus.SUCCESS + assert http_status_to_exit_status(101) == ExitStatus.SUCCESS + assert http_status_to_exit_status(102) == ExitStatus.SUCCESS + + +def test_success_status_codes(): + """Test that 2xx status codes return SUCCESS.""" + assert http_status_to_exit_status(200) == ExitStatus.SUCCESS + assert http_status_to_exit_status(201) == ExitStatus.SUCCESS + assert http_status_to_exit_status(204) == ExitStatus.SUCCESS + assert http_status_to_exit_status(299) == ExitStatus.SUCCESS + + +def test_redirect_status_codes_without_follow(): + """Test that 3xx status codes return ERROR_HTTP_3XX when not following.""" + assert http_status_to_exit_status(300, follow=False) == ExitStatus.ERROR_HTTP_3XX + assert http_status_to_exit_status(301, follow=False) == ExitStatus.ERROR_HTTP_3XX + assert http_status_to_exit_status(302, follow=False) == ExitStatus.ERROR_HTTP_3XX + assert http_status_to_exit_status(399, follow=False) == ExitStatus.ERROR_HTTP_3XX + + +def test_redirect_status_codes_with_follow(): + """Test that 3xx status codes return SUCCESS when following redirects.""" + assert http_status_to_exit_status(300, follow=True) == ExitStatus.SUCCESS + assert http_status_to_exit_status(301, follow=True) == ExitStatus.SUCCESS + assert http_status_to_exit_status(302, follow=True) == ExitStatus.SUCCESS + + +def test_client_error_status_codes(): + """Test that 4xx status codes return ERROR_HTTP_4XX.""" + assert http_status_to_exit_status(400) == ExitStatus.ERROR_HTTP_4XX + assert http_status_to_exit_status(404) == ExitStatus.ERROR_HTTP_4XX + assert http_status_to_exit_status(499) == ExitStatus.ERROR_HTTP_4XX + + +def test_server_error_status_codes(): + """Test that 5xx status codes return ERROR_HTTP_5XX.""" + assert http_status_to_exit_status(500) == ExitStatus.ERROR_HTTP_5XX + assert http_status_to_exit_status(503) == ExitStatus.ERROR_HTTP_5XX + assert http_status_to_exit_status(599) == ExitStatus.ERROR_HTTP_5XX + + +def test_invalid_status_codes(): + """Test that invalid/unknown status codes are handled. + + Status codes outside the standard ranges (600+, negative, etc.) + should return an error status rather than SUCCESS. + """ + # Status codes >= 600 are not defined in HTTP spec + result = http_status_to_exit_status(600) + assert result == ExitStatus.ERROR + + result = http_status_to_exit_status(999) + assert result == ExitStatus.ERROR + + # Negative status codes don't make sense + result = http_status_to_exit_status(-1) + assert result == ExitStatus.ERROR + + result = http_status_to_exit_status(0) + assert result == ExitStatus.ERROR