Skip to content

Inconsistent behaviour in query string matching with spaces #370

Open
@WillMorrisonEnspi

Description

@WillMorrisonEnspi

It seems like the type (string vs dict) of query_string affects the behaviour of the resulting matcher when the query string in the request has percent-encoding. Specifically, a string typed argument to query_string must match exactly the query string in the request. However, a dict typed argument to query_string must match the request's query string after unquoting.

Reproduced with pytest-httpserver version 1.1.0

test file:

import unittest
import pytest_httpserver
import requests

class TestRepro(unittest.TestCase):

    def test_query_string_with_spaces_string_fails(self):
        with pytest_httpserver.HTTPServer() as httpserver:
            httpserver.expect_request("/test", query_string="foo=bar baz").respond_with_data("OK")

            url = httpserver.url_for("/test") + "?foo=bar baz"
            requests.get(url)
            httpserver.check_assertions()

    def test_query_string_is_encoded_string_passes(self):
        with pytest_httpserver.HTTPServer() as httpserver:
            httpserver.expect_request("/test", query_string="foo=bar%20baz").respond_with_data("OK")

            url = httpserver.url_for("/test") + "?foo=bar baz"
            requests.get(url)
            httpserver.check_assertions()

    def test_query_string_with_spaces_dict_passes(self):
        with pytest_httpserver.HTTPServer() as httpserver:
            httpserver.expect_request("/test", query_string={"foo": "bar baz"}).respond_with_data("OK")

            url = httpserver.url_for("/test") + "?foo=bar baz"
            requests.get(url)
            httpserver.check_assertions()

    def test_query_string_is_encoded_dict_fails(self):
        with pytest_httpserver.HTTPServer() as httpserver:
            httpserver.expect_request("/test", query_string={"foo": "bar%20baz"}).respond_with_data("OK")

            url = httpserver.url_for("/test") + "?foo=bar baz"
            requests.get(url)
            httpserver.check_assertions()

Output:

$ python -m unittest repro.py
127.0.0.1 - - [02/Oct/2024 16:36:41] "GET /test?foo=bar%20baz HTTP/1.1" 500 -
F127.0.0.1 - - [02/Oct/2024 16:36:41] "GET /test?foo=bar%20baz HTTP/1.1" 200 -
.127.0.0.1 - - [02/Oct/2024 16:36:41] "GET /test?foo=bar%20baz HTTP/1.1" 200 -
.127.0.0.1 - - [02/Oct/2024 16:36:41] "GET /test?foo=bar%20baz HTTP/1.1" 500 -
F
======================================================================
FAIL: test_query_string_is_encoded_dict_fails (repro.TestRepro.test_query_string_is_encoded_dict_fails)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/wmorrison/code/aws_lambda/repro.py", line 37, in test_query_string_is_encoded_dict_fails
    httpserver.check_assertions()
  File "/home/wmorrison/.local/share/pyenv/versions/3.11.5/envs/3.11.5-enspired@aws_lambda/lib/python3.11/site-packages/pytest_httpserver/httpserver.py", line 818, in check_assertions
    raise AssertionError(assertion)
AssertionError: No handler found for request <Request 'http://localhost:38771/test?foo=bar%20baz' [GET]> with data b''.Ordered matchers:
    none

Oneshot matchers:
    none

Persistent matchers:
    <RequestMatcher uri='/test' method='__ALL' query_string={'foo': 'bar%20baz'} headers={} data=None json=<UNDEFINED>>

======================================================================
FAIL: test_query_string_with_spaces_string_fails (repro.TestRepro.test_query_string_with_spaces_string_fails)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/wmorrison/code/aws_lambda/repro.py", line 13, in test_query_string_with_spaces_string_fails
    httpserver.check_assertions()
  File "/home/wmorrison/.local/share/pyenv/versions/3.11.5/envs/3.11.5-enspired@aws_lambda/lib/python3.11/site-packages/pytest_httpserver/httpserver.py", line 818, in check_assertions
    raise AssertionError(assertion)
AssertionError: No handler found for request <Request 'http://localhost:35185/test?foo=bar%20baz' [GET]> with data b''.Ordered matchers:
    none

Oneshot matchers:
    none

Persistent matchers:
    <RequestMatcher uri='/test' method='__ALL' query_string='foo=bar baz' headers={} data=None json=<UNDEFINED>>

----------------------------------------------------------------------
Ran 4 tests in 0.014s

FAILED (failures=2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions