_build_request() used header_dict.setdefault("Content-Type", "application/json") when encoding a mapping body. That lookup is case-sensitive, so a caller-supplied content-type / CONTENT-TYPE header was ignored and urllib.request.Request later collapsed both names, overwriting the custom value with application/json.
This change only adds the JSON default when no existing header name matches content-type case-insensitively. The caller mapping is copied first, so it is left unchanged.
Issue #87 documents that headers={"content-type": "application/merge-patch+json"} with a dict body produced Content-type: application/json on the request. That can change how an API interprets the payload.
Implementation
In src/pythonnative/net.py, replace setdefault("Content-Type", ...) with:
Added parameterized tests in tests/test_net.py that construct requests with _build_request() (no network):
Content-Type, content-type, CONTENT-TYPE, and Content-type all keep application/merge-patch+json
exactly one content-type header remains on the request
the original headers mapping is unchanged
the body still decodes to the original JSON object
a mapping body with no content-type still gets application/json
Checks performed in this environment:
Isolated reproduction of _build_request header assembly on Python 3.12 (project requires 3.13 for the full package import). Result: all four casings preserved a single application/merge-patch+json header; default path still sets application/json.
Full uv run pytest tests/test_net.py -q and ./scripts/check.sh were not run here because Python 3.13 is not available on this runner. Please rely on CI for those.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_build_request() used header_dict.setdefault("Content-Type", "application/json") when encoding a mapping body. That lookup is case-sensitive, so a caller-supplied content-type / CONTENT-TYPE header was ignored and urllib.request.Request later collapsed both names, overwriting the custom value with application/json.
This change only adds the JSON default when no existing header name matches content-type case-insensitively. The caller mapping is copied first, so it is left unchanged.
Fixes #87
Motivation
Issue #87 documents that headers={"content-type": "application/merge-patch+json"} with a dict body produced Content-type: application/json on the request. That can change how an API interprets the payload.
Implementation
In src/pythonnative/net.py, replace setdefault("Content-Type", ...) with:
JSON encoding of mapping bodies is unchanged.
Testing
Added parameterized tests in tests/test_net.py that construct requests with _build_request() (no network):
Checks performed in this environment: