diff --git a/httpie/output/formatters/json.py b/httpie/output/formatters/json.py index bc6151e42f..a3a1aad9d6 100644 --- a/httpie/output/formatters/json.py +++ b/httpie/output/formatters/json.py @@ -10,6 +10,7 @@ def __init__(self, **kwargs): self.enabled = self.format_options['json']['format'] def format_body(self, body: str, mime: str) -> str: + mime = mime.lower() maybe_json = [ 'json', 'javascript', diff --git a/tests/test_output.py b/tests/test_output.py index 2242177dbc..ed713bafcb 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -629,3 +629,41 @@ def test_response_mime_overwrite_incorrect(): # The provided Content-Type is simply ignored, and so no formatting is done. r = http('--response-mime=incorrect/type', DUMMY_URL) assert XML_DATA_RAW in r + + +class TestJSONFormatterMIME: + """JSONFormatter must match the body MIME type case-insensitively (#1958).""" + + @staticmethod + def make_formatter(): + from httpie.output.formatters.json import JSONFormatter + return JSONFormatter( + format_options={'json': {'format': True, 'sort_keys': True, 'indent': 4}}, + explicit_json=False, + ) + + @pytest.mark.parametrize( + 'mime', + [ + 'application/json', + 'APPLICATION/JSON', + 'Application/Problem+JSON; charset=UTF-8', + ] + ) + def test_format_body_matches_mime_case_insensitively(self, mime: str): + formatted = self.make_formatter().format_body('{"a": 1}', mime) + assert '\n' in formatted + assert json.loads(formatted) == {'a': 1} + + @pytest.mark.parametrize( + 'mime', + [ + 'text/plain', + 'application/xml', + ] + ) + def test_format_body_case_parity_for_non_json(self, mime: str): + # An upper-cased MIME type behaves exactly like its lower-case form. + body = '{"a": 1}' + formatter = self.make_formatter() + assert formatter.format_body(body, mime.upper()) == formatter.format_body(body, mime)