From 0cfa11b1a566c5c12ff657502ec8e7f4d354c7e9 Mon Sep 17 00:00:00 2001 From: alufers Date: Mon, 25 May 2026 13:28:20 +0200 Subject: [PATCH] Prevent headers from overwriting params --- mitmproxy2swagger/har_capture_reader.py | 1 + mitmproxy2swagger/mitmproxy2swagger.py | 17 ++++----- mitmproxy2swagger/test_mitmproxy2swagger.py | 18 ++++++++++ testdata/headers_and_params_har.har | 39 +++++++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 testdata/headers_and_params_har.har diff --git a/mitmproxy2swagger/har_capture_reader.py b/mitmproxy2swagger/har_capture_reader.py index 4f790fa..e3d9851 100644 --- a/mitmproxy2swagger/har_capture_reader.py +++ b/mitmproxy2swagger/har_capture_reader.py @@ -60,6 +60,7 @@ class HarFlowWrapper: # create list on key if it does not exist headers[k] = headers.get(k, []) headers[k].append(v) + return headers def get_request_body(self): if ( diff --git a/mitmproxy2swagger/mitmproxy2swagger.py b/mitmproxy2swagger/mitmproxy2swagger.py index f7b39c0..71d8faa 100644 --- a/mitmproxy2swagger/mitmproxy2swagger.py +++ b/mitmproxy2swagger/mitmproxy2swagger.py @@ -215,19 +215,20 @@ def main(override_args: Sequence[str] | None = None): ) params = swagger_util.url_to_params(url, path_template_to_set) + all_params = [] if args.headers: headers_request = swagger_util.request_to_headers( req.get_request_headers() ) if headers_request is not None and len(headers_request) > 0: - set_key_if_not_exists( - swagger["paths"][path_template_to_set][method], - "parameters", - headers_request + (params or []), - ) + all_params.extend(headers_request) if params is not None and len(params) > 0: + all_params.extend(params) + if len(all_params) > 0: set_key_if_not_exists( - swagger["paths"][path_template_to_set][method], "parameters", params + swagger["paths"][path_template_to_set][method], + "parameters", + all_params, ) if method not in ["get", "head"]: @@ -264,9 +265,9 @@ def main(override_args: Sequence[str] | None = None): did_find_anything = False for key, value in body_val_bytes.items(): did_find_anything = True - if type(key) != str: + if isinstance(key, bytes): key = key.decode("utf-8") - if type(value) != str: + if isinstance(value, bytes): value = value.decode("utf-8") body_val[key] = value if did_find_anything: diff --git a/mitmproxy2swagger/test_mitmproxy2swagger.py b/mitmproxy2swagger/test_mitmproxy2swagger.py index f179be6..9a53080 100644 --- a/mitmproxy2swagger/test_mitmproxy2swagger.py +++ b/mitmproxy2swagger/test_mitmproxy2swagger.py @@ -141,6 +141,24 @@ def test_mitmproxy2swagger_generates_headers_for_flow_files(): ) +def test_mitmproxy2swagger_includes_both_headers_and_query_params_with_hd_flag(): + # Regression test for https://github.com/alufers/mitmproxy2swagger/pull/220 + # With --headers, query params were dropped; without it, headers were dropped + data = mitmproxy2swagger_e2e_test( + "testdata/headers_and_params_har.har", + "https://httpbin.org/", + ["--headers"], + ) + assert data is not None + + parameters = get_nested_key(data, "paths./get.get.parameters") + assert parameters is not None + + param_names = [p["name"] for p in parameters] + assert "X-Api-Key" in param_names, "Request header missing from parameters" + assert "search" in param_names, "Query parameter missing from parameters" + + def test_mitmproxy2swagger_parses_msgpack_requests_and_responses(): data = mitmproxy2swagger_e2e_test( "testdata/msgpack_flows", diff --git a/testdata/headers_and_params_har.har b/testdata/headers_and_params_har.har new file mode 100644 index 0000000..d669cad --- /dev/null +++ b/testdata/headers_and_params_har.har @@ -0,0 +1,39 @@ +{ + "log": { + "version": "1.2", + "creator": { "name": "test", "version": "1.0" }, + "entries": [ + { + "request": { + "method": "GET", + "url": "https://httpbin.org/get?search=test", + "headers": [ + { "name": "X-Api-Key", "value": "mykey" } + ], + "queryString": [ + { "name": "search", "value": "test" } + ], + "cookies": [], + "headersSize": -1, + "bodySize": 0 + }, + "response": { + "status": 200, + "statusText": "OK", + "headers": [ + { "name": "Content-Type", "value": "application/json" } + ], + "cookies": [], + "content": { "size": 2, "mimeType": "application/json", "text": "{}" }, + "redirectURL": "", + "headersSize": -1, + "bodySize": 2 + }, + "cache": {}, + "timings": { "send": 0, "wait": 1, "receive": 1 }, + "startedDateTime": "2024-01-01T00:00:00.000Z", + "time": 2 + } + ] + } +}