From 24490499ee4aa7d79e925539e09f9472954da7b6 Mon Sep 17 00:00:00 2001 From: Harsh Thakkar Date: Thu, 24 Sep 2026 08:21:33 +0530 Subject: [PATCH] fix: --multipart silently drops := / :=@ JSON fields SEPARATORS_GROUP_MULTIPART is missing SEPARATOR_DATA_RAW_JSON (:=) and SEPARATOR_DATA_EMBED_RAW_JSON_FILE (:=@), so ProcessMultiItemArgs routed those items only into args.data - which the multipart encoder never reads (get_multipart_data_and_content_type only consumes args.multipart_data). JSON primitive values in --multipart requests vanished silently, unlike --form, whose advertised support for the JSON field syntax is shared in the changelog. Add both separators; complex values still raise the existing 'Cannot use complex JSON value types' ParseError. --- httpie/cli/constants.py | 2 ++ tests/test_json.py | 31 +++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/httpie/cli/constants.py b/httpie/cli/constants.py index 09ca19e4af..a9bed8e12b 100644 --- a/httpie/cli/constants.py +++ b/httpie/cli/constants.py @@ -37,8 +37,10 @@ SEPARATORS_GROUP_MULTIPART = frozenset({ SEPARATOR_DATA_STRING, + SEPARATOR_DATA_RAW_JSON, SEPARATOR_DATA_EMBED_FILE_CONTENTS, SEPARATOR_FILE_UPLOAD, + SEPARATOR_DATA_EMBED_RAW_JSON_FILE, }) # Separators for items whose value is a filename to be embedded diff --git a/tests/test_json.py b/tests/test_json.py index e758ebe7f4..86bb6bd197 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -132,15 +132,42 @@ def test_duplicate_keys_support_from_input_file(): @pytest.mark.parametrize('value', [1, 1.1, True, 'some_value']) -def test_simple_json_arguments_with_non_json(httpbin, value): +@pytest.mark.parametrize('form_request_type', ['--form', '--multipart']) +def test_simple_json_arguments_with_non_json(httpbin, value, form_request_type): r = http( - '--form', + form_request_type, httpbin + '/post', f'option:={json.dumps(value)}', ) assert r.json['form'] == {'option': str(value)} +def test_simple_json_arguments_with_non_json_and_multipart_embed( + httpbin, tmp_path +): + # :=@ embeds a JSON file's value; it must reach the multipart body too. + json_file = tmp_path / 'value.json' + json_file.write_text(json.dumps([1, 2, 3])) + with pytest.raises(ParseError) as cm: + http( + '--multipart', + httpbin + '/post', + f'complex:=@{json_file}', + 'plain=value', + ) + cm.match('Cannot use complex JSON value types') + + scalar_file = tmp_path / 'scalar.json' + scalar_file.write_text('42') + r = http( + '--multipart', + httpbin + '/post', + f'scalar:=@{scalar_file}', + 'plain=value', + ) + assert r.json['form'] == {'scalar': '42', 'plain': 'value'} + + @pytest.mark.parametrize( 'request_type', [