strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations 🍓
https://strawberry.rocks
MIT License
4k stars 530 forks source link

Malformed request with `operationName` that isn't in `query` gives 500 error: `Can't get GraphQL operation type` #3288

Open huonw opened 10 months ago

huonw commented 10 months ago

Describe the Bug

Strawberry throws an uncaught RuntimeError("Can't get GraphQL operation type") resulting in a 500 server error for a request that provides an operationName that isn't in the query, e.g.

{
  "query":"query test { example }",
  "operationName":"different"
}

This is an invalid/malformed request (that is, a client problem), and thus should at most be a 4xx error, or maybe a 200 with error details in the response like other sorts of errors.

Reproducer: start a server (e.g. a minimal one like the following):

cd $(mktemp -d)

python -m venv .venv
. .venv/bin/activate

pip install 'strawberry-graphql[debug-server]==0.216.1'

cat > app.py <<EOF
import strawberry

@strawberry.type
class Query:
    @strawberry.field
    @staticmethod
    def example() -> str:
        return ""

schema = strawberry.Schema(Query)
EOF

python -m strawberry server app:schema

Run a request like:

curl -i 'http://localhost:8765/graphql' -X 'POST' -H 'Content-Type: application/json' --data-binary '{"query":"query test { example }","operationName":"different"}'

The output looks like:

HTTP/1.1 500 Internal Server Error
date: Wed, 13 Dec 2023 04:33:51 GMT
server: uvicorn
content-length: 3493
content-type: text/plain; charset=utf-8

Traceback (most recent call last):
  File ".../.venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File ".../.venv/lib/python3.9/site-packages/starlette/middleware/cors.py", line 83, in __call__
    await self.app(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/starlette/_exception_handler.py", line 55, in wrapped_app
    raise exc
  File ".../.venv/lib/python3.9/site-packages/starlette/_exception_handler.py", line 44, in wrapped_app
    await app(scope, receive, sender)
  File ".../.venv/lib/python3.9/site-packages/starlette/routing.py", line 754, in __call__
    await self.middleware_stack(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/starlette/routing.py", line 774, in app
    await route.handle(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/starlette/routing.py", line 296, in handle
    await self.app(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/strawberry/asgi/__init__.py", line 122, in __call__
    return await self.handle_http(scope, receive, send)
  File ".../.venv/lib/python3.9/site-packages/strawberry/asgi/__init__.py", line 189, in handle_http
    response = await self.run(request)
  File ".../.venv/lib/python3.9/site-packages/strawberry/http/async_base_view.py", line 185, in run
    result = await self.execute_operation(
  File ".../.venv/lib/python3.9/site-packages/strawberry/http/async_base_view.py", line 117, in execute_operation
    return await self.schema.execute(
  File ".../.venv/lib/python3.9/site-packages/strawberry/schema/schema.py", line 256, in execute
    result = await execute(
  File ".../.venv/lib/python3.9/site-packages/strawberry/schema/execute.py", line 125, in execute
    if execution_context.operation_type not in allowed_operation_types:
  File ".../.venv/lib/python3.9/site-packages/strawberry/types/execution.py", line 78, in operation_type
    return get_operation_type(graphql_document, self.operation_name)
  File ".../.venv/lib/python3.9/site-packages/strawberry/utils/operation.py", line 38, in get_operation_type
    raise RuntimeError("Can't get GraphQL operation type")
Fully pinned set of transitive dependencies ``` anyio==4.1.0 click==8.1.7 exceptiongroup==1.2.0 graphql-core==3.2.3 h11==0.14.0 idna==3.6 libcst==1.1.0 markdown-it-py==3.0.0 mdurl==0.1.2 mypy-extensions==1.0.0 Pygments==2.17.2 python-dateutil==2.8.2 python-multipart==0.0.6 PyYAML==6.0.1 rich==13.7.0 six==1.16.0 sniffio==1.3.0 starlette==0.33.0 strawberry-graphql==0.216.1 typer==0.9.0 typing-inspect==0.9.0 typing_extensions==4.9.0 uvicorn==0.24.0.post1 ```

System Information

Additional Context

Thanks for strawberry! 🍓

3120 is potentially related but that doesn't have a reproducer so I'm not 100% sure 😄

Upvote & Fund

Fund with Polar

StephenKappel commented 3 months ago

This appears to be fixed in 0.235.2. (Or more exactly, in some release after 0.220.0 and before or at 0.235.2.) The response is now a 200 status code.