Skip to content

Commit 2c27a98

Browse files
authored
Fix invalid query parameters were not handled (#3927)
* Fix handling of invalid query parameter * Add release file * Use more precise error message
1 parent 8a14ab4 commit 2c27a98

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

RELEASE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Release type: patch
2+
3+
In this release, we updated Strawberry to gracefully handle requests containing
4+
an invalid `query` parameter. Previously, such requests could result in internal
5+
server errors, but now they will return a 400 Bad Request response with an
6+
appropriate error message, conforming to the GraphQL over HTTP specification.

strawberry/http/async_base_view.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,15 @@ async def parse_http_body(
529529
else:
530530
raise HTTPException(400, "Unsupported content type")
531531

532+
query = data.get("query")
533+
if not isinstance(query, (str, type(None))):
534+
raise HTTPException(
535+
400,
536+
"The GraphQL operation's `query` must be a string or null, if provided.",
537+
)
538+
532539
return GraphQLRequestData(
533-
query=data.get("query"),
540+
query=query,
534541
variables=data.get("variables"),
535542
operation_name=data.get("operationName"),
536543
extensions=data.get("extensions"),

strawberry/http/sync_base_view.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,15 @@ def parse_http_body(self, request: SyncHTTPRequestAdapter) -> GraphQLRequestData
154154
else:
155155
raise HTTPException(400, "Unsupported content type")
156156

157+
query = data.get("query")
158+
if not isinstance(query, (str, type(None))):
159+
raise HTTPException(
160+
400,
161+
"The GraphQL operation's `query` must be a string or null, if provided.",
162+
)
163+
157164
return GraphQLRequestData(
158-
query=data.get("query"),
165+
query=query,
159166
variables=data.get("variables"),
160167
operation_name=data.get("operationName"),
161168
extensions=data.get("extensions"),

tests/http/test_graphql_over_http_spec.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,6 @@ async def test_423l(http_client):
214214
assert response.status_code == 400
215215

216216

217-
@pytest.mark.xfail(
218-
reason="OPTIONAL - Currently results in lots of TypeErrors",
219-
raises=AssertionError,
220-
)
221217
@pytest.mark.parametrize(
222218
"invalid",
223219
[{"obj": "ect"}, 0, False, ["array"]],

tests/http/test_query.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,30 @@ async def test_missing_query(http_client: HttpClient):
196196
assert "No GraphQL query found in the request" in response.text
197197

198198

199+
@pytest.mark.parametrize(
200+
"not_stringified_json",
201+
[{"obj": "ect"}, 0, False, ["array"]],
202+
)
203+
async def test_requests_with_invalid_query_parameter_are_rejected(
204+
http_client: HttpClient, not_stringified_json
205+
):
206+
response = await http_client.query(
207+
query=not_stringified_json,
208+
)
209+
210+
assert response.status_code == 400
211+
message = "The GraphQL operation's `query` must be a string or null, if provided."
212+
213+
if isinstance(http_client, ChaliceHttpClient):
214+
# Our Chalice integration purposely wraps errors messages with a JSON object
215+
assert response.json == {
216+
"Code": "BadRequestError",
217+
"Message": message,
218+
}
219+
else:
220+
assert response.data == message.encode()
221+
222+
199223
@pytest.mark.parametrize("method", ["get", "post"])
200224
async def test_query_context(method: Literal["get", "post"], http_client: HttpClient):
201225
response = await http_client.query(

0 commit comments

Comments
 (0)