From b849a0b47d7bfd530d69017b0f76be5efd496218 Mon Sep 17 00:00:00 2001 From: Ana Ryerson Date: Sun, 30 Nov 2025 18:55:28 -0500 Subject: [PATCH] Add support for embedded headers; include tests for valid and malformed headers --- httpie/cli/requestitems.py | 26 +++++++++++++++++++--- test_headers.py | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 test_headers.py diff --git a/httpie/cli/requestitems.py b/httpie/cli/requestitems.py index 8931b88ac7..733090e423 100644 --- a/httpie/cli/requestitems.py +++ b/httpie/cli/requestitems.py @@ -109,9 +109,16 @@ def from_args( processor_func, target_dict = rules[arg.sep] value = processor_func(arg) + # NEW: handle multi-header files + if isinstance(value, list): + # value is a list of (key, value) pairs + for k, v in value: + target_dict.add(k, v) + continue # Skip normal handling + + # Normal case if arg.sep in SEPARATORS_GROUP_MULTIPART: instance.multipart_data[arg.key] = value - if isinstance(target_dict, BaseMultiDict): target_dict.add(arg.key, value) else: @@ -127,8 +134,21 @@ def process_header_arg(arg: KeyValueArg) -> Optional[str]: return arg.value or None -def process_embed_header_arg(arg: KeyValueArg) -> str: - return load_text_file(arg).rstrip('\n') +def process_embed_header_arg(arg: KeyValueArg): + text = load_text_file(arg).rstrip('\n') + lines = [line.strip() for line in text.splitlines() if line.strip()] + + header_pairs = [] + + for i, line in enumerate(lines, start=1): + if ':' not in line: + raise ParseError(f"{arg.orig!r}: Malformed header on line {i}: {line!r}") + + key, value = line.split(':', 1) + header_pairs.append((key.strip(), value.strip())) + + return header_pairs + def process_empty_header_arg(arg: KeyValueArg) -> str: diff --git a/test_headers.py b/test_headers.py new file mode 100644 index 0000000000..9e7fa1ea1a --- /dev/null +++ b/test_headers.py @@ -0,0 +1,44 @@ +import pytest +from httpie.cli.requestitems import RequestItems +from httpie.cli.argtypes import KeyValueArg +from httpie.cli.constants import SEPARATOR_HEADER_EMBED +from httpie.cli.exceptions import ParseError + + +def load_request_items(file_name: str): + """Helper to create RequestItems from a header file.""" + arg = KeyValueArg( + key=None, + value=file_name, + sep=SEPARATOR_HEADER_EMBED, + orig=f"@{file_name}" + ) + return RequestItems.from_args([arg]) + + +def test_headers_txt(): + req_items = load_request_items('headers.txt') + expected = { + "X-API-Key": "12345", + "User-Agent": "MyApp/1.0", + "Accept": "application/json", + } + for k, v in expected.items(): + assert req_items.headers.get(k) == v + + +def test_headers_with_empty_lines_txt(): + req_items = load_request_items('headers_with_empty_lines.txt') + expected = { + "X-API-Key": "12345", + "User-Agent": "MyApp/1.0", + "Accept": "application/json", + } + for k, v in expected.items(): + assert req_items.headers.get(k) == v + + +def test_headers_malformed_txt(): + # This file intentionally has a malformed header; should raise ParseError + with pytest.raises(ParseError): + load_request_items('headers_malformed.txt')