Skip to content

Match parsed form fields in request expectations - #520

Open
sricharanreddycheruku wants to merge 3 commits into
csernazs:masterfrom
sricharanreddycheruku:match-form-data
Open

sricharanreddycheruku wants to merge 3 commits into
csernazs:masterfrom
sricharanreddycheruku:match-form-data

Conversation

@sricharanreddycheruku

@sricharanreddycheruku sricharanreddycheruku commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Matching form-encoded request bodies currently requires a custom handler. This adds the data_form argument proposed in #369 to compare Werkzeug's parsed form fields.

A mapping compares the first value for each field, while a MultiDict compares all repeated values, consistently with query-string matching. Extra fields and missing empty-valued fields do not match. The raw body remains available to response handlers, and form expectations are mutually exclusive with data and json.

The argument is available on normal, oneshot, ordered, baked and blocking expectations. Existing positional arguments and representations remain unchanged. When the new argument is unused, it is not forwarded to custom matcher factories or expectation overrides. Includes a how-to example, API docstrings, a release note and the updated source-package test inventory.

Original submission validation on Linux / Python 3.12.14 using locked development dependencies with Poetry 2.1.1:

  • All 17 new test cases fail on the original source because data_form is absent.
  • Focused matcher, baked and blocking tests: 39 passed.
  • Full HTTP and packaging suite (pytest -q tests --release): 171 passed, 3 skipped, 2 xfailed; one existing tar-extraction warning.
  • Existing HTTPS suite (pytest -q tests --ssl): 1 passed, 175 skips from SSL selection.
  • Mypy: no issues in 58 source files.
  • make precommit and git diff --check: passed.
  • make doc: passed; the same 59 warnings occur on unchanged source, with no new warnings.

Fixes #369

Revision after maintainer review:

  • Removed the newly added keyword-only separators before data_form.
  • Moved the form example into tests/examples/test_howto_form_data.py and included that tested file in the how-to documentation.
  • Specified application/x-www-form-urlencoded and multipart/form-data as the Content-Type values Werkzeug uses to parse form fields.

Revision validation on Linux / Python 3.12.3 with pip-installed development dependencies and Poetry 2.1.1, rather than a lockfile installation:

  • Full HTTP and packaging suite: 172 passed, 3 skipped, 2 xfailed, one existing warning.
  • HTTPS selection: 1 passed, 176 skipped.
  • Form matching and tested documentation example: 16 passed.
  • Mypy: no issues in 59 source files.
  • All applicable pre-commit hooks passed.
  • Fresh documentation build succeeded with 59 warnings, matching the unchanged PR head.
  • git diff --check passed.

Comment thread doc/howto.rst Outdated
Use ``data_form`` to match parsed form fields without depending on their encoded
order or spelling:

.. code-block:: python

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @sricharanreddycheruku ,

Could you move this python code example to the tests/examples folder and reference it from the docs? This is how I set up that we test the examples as well.

You can find example like this:

.. literalinclude :: ../tests/examples/test_example_query_params1.py
   :language: python

You can also build documentation locally with "make doc" and run "make doc-preview" to show the index.html in your default browser.

Comment thread pytest_httpserver/httpserver.py Outdated
query_string: QueryMatcher | str | bytes | Mapping[str, str] | None = None,
header_value_matcher: HVMATCHER_T | None = None,
json: Any = UNDEFINED,
*,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it a kwarg-only?

Personally I think all option should be kwarg only, but I don't want to introduce API breaking. But adding this here just results a half-fixed thing.

Could you remove this if you are ok with it? I mean the *, only.

And in the other places as well.

@csernazs

csernazs commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Thanks for your PR, I have a few comments only, otherwise looks good to me.

Comment thread doc/howto.rst Outdated
``werkzeug.datastructures.MultiDict`` to match all values of repeated fields.
Extra fields do not match, and an empty value is distinct from a missing field.

Werkzeug parses form fields using the request's ``Content-Type`` header.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be reworded. I think you wanted to write that werkzeug parses form fields if the content-type header is X. I think we should also include the value of the content-type header here.

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.

Support for x-www-form-urlencoded

2 participants