Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON path traversing raises exception rather than not using the route #182

Closed
dariobauer opened this issue Nov 7, 2021 · 2 comments · Fixed by #184
Closed

JSON path traversing raises exception rather than not using the route #182

dariobauer opened this issue Nov 7, 2021 · 2 comments · Fixed by #184
Labels
bug Something isn't working enhancement New feature or request

Comments

@dariobauer
Copy link

Thanks for developing and documenting repsx, it is extremely useful.

One such useful features is the json pattern path traversing.
However I am having an issue that if I don't have a matching pattern before one where I use path traversing I get an error if my request has json but not that key.

#conftest.py
@pytest.fixture(scope="module")
def mock_auth_api():
    with respx.mock(base_url="https://login.example.com/") as respx_mock:
        example_route = respx_mock.post(
            path__regex=r"([0-9a-zA-Z-]+)/oauth2/token$",
            json__grant_type="refresh_token",
        ).mock(side_effect=my_side_effect)
        yield respx_mock

#example_test.py
request_url = "https://app.diffhost.net/items/hFj8G5/endpoint"
headers = {"Accept": "*/*", "Authorization": "Bearer 123" }
json = {"type": "example"}
response = httpx.post(request_url, headers=headers, json=body)

Result:

self = <JSON eq '"refresh_token"'>, request = <Request('POST', 'https://app.diffhost.net/items/hFj8G5/endpoint')>

    def parse(self, request: httpx.Request) -> str:
        content = super().parse(request)
        try:
            json = jsonlib.loads(content.decode("utf-8"))
        except JSONDecodeError:
            return ""
    
        if self.path:
            value = json
            for bit in self.path.split("__"):
                key = int(bit) if bit.isdigit() else bit
                try:
                    value = value[key]
                except KeyError as e:
>                   raise KeyError(f"{self.path!r} not in {json!r}") from e
E                   KeyError: "'grant_type' not in {'type': 'example'}"

Expected:

I would expect the KeyError to result in a non-match pattern, not an exception being raised.

Additionally it seems odd to me that since the base_url and path both do not match that the rest of the pattern is even checked. I presume using pattern = M(path...) & M(json...) would not change this?

@lundberg
Copy link
Owner

lundberg commented Nov 8, 2021

Thanks for reporting this issue @dariobauer!

I would expect the KeyError to result in a non-match pattern, not an exception being raised.

Totally agree here, it feels more natural that this KeyError is silenced and failing the match instead 👍

Additionally it seems odd to me that since the base_url and path both do not match that the rest of the pattern is even checked.

Also a good point, it would at least enhance the performance/speed if a failed pattern could omit the preceding pattern matching of a route.

I presume using pattern = M(path...) & M(json...) would not change this?

Correct, that wouldn't change anything, e.g. M(path=...) is just a shortcut to Path(...) and the AND operator.

@lundberg lundberg added bug Something isn't working enhancement New feature or request labels Nov 8, 2021
@dariobauer
Copy link
Author

Thanks for your prompt response and these prs, much appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants