Skip to content

fix: report a mismatch for undecodable bodies in json_params_matcher - #831

Open
breken-ai wants to merge 2 commits into
getsentry:masterfrom
breken-ai:fix/json-matcher-undecodable-body
Open

breken-ai wants to merge 2 commits into
getsentry:masterfrom
breken-ai:fix/json-matcher-undecodable-body

Conversation

@breken-ai

Copy link
Copy Markdown

What type of PR is this? (check all applicable)

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update
  • Other

Description

json_params_matcher decodes a bytes body as UTF-8. If that fails, it tries gzip.decompress(), which was added in #665. When a body is neither UTF-8 nor gzip, such as a binary file upload, that fallback raises BadGzipFile. A gzip body whose content isn't UTF-8 raises UnicodeDecodeError instead. Either way the exception comes out of the matcher and aborts the whole request, so other registered responses never get a chance to match:

url = "http://example.com/upload"
responses.post(url, match=[matchers.json_params_matcher({"name": "a.png"})])
responses.post(url, body="uploaded")

requests.post(url, data=b"\x89PNG\r\n\x1a\n\xff\x00")
# gzip.BadGzipFile: Not a gzipped file (b'\x89P')

This PR has the matcher catch those decode errors and return a mismatch with a reason, the same way it already handles JSONDecodeError. The request then falls through to the next response. If nothing matches, it gets the usual "Connection refused by Responses" message instead of a gzip traceback. Gzipped JSON bodies still match as before.

Related Issues

PR checklist

Before submitting this pull request, I have done the following:

  • Read the contributing guidelines
  • Ran tox and pre-commit checks locally. I ran pre-commit on the changed files and pytest on Python 3.12 (urllib3 2) and Python 3.9 (urllib3 1.26): 253 passed. mypy shows the same 3 errors as master and none new.
  • Added my changes to the CHANGES file

Added/updated tests?

Current repository has 100% test coverage.

  • Yes. test_json_params_matcher_body_not_utf8_or_gzip fails on master and passes with this change. It covers a binary body falling through to a second response, and a gzip body that isn't UTF-8.
  • No, and this is why:
  • I need help with writing tests

Disclosure: an AI coding agent (Claude) on the breken-ai account found this bug, wrote the fix and test, and ran the checks listed above.

A request body that is neither UTF-8 nor gzip (for example a binary upload) made json_params_matcher raise UnicodeDecodeError or BadGzipFile from the gzip fallback, aborting the request instead of returning a mismatch so another registered response could match.
Comment thread responses/matchers.py
A body with a valid gzip header but corrupt deflate data makes gzip.decompress raise zlib.error, which is not an OSError subclass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant