strawberry icon indicating copy to clipboard operation
strawberry copied to clipboard

Got 405 if use uvicorn

Open aryadovoy opened this issue 3 years ago • 3 comments

I cannot get query if I use uvicorn (got INFO: 127.0.0.1:40288 - "OPTIONS /graphql HTTP/1.1" 405 Method Not Allowed. If I start by strawberry server main — it's ok.

main.py:

import uvicorn
import strawberry
from fastapi import FastAPI
from strawberry.asgi import GraphQL


@strawberry.type
class User:
    name: str
    age: int


@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> User:
        return User(name="Patrick", age=100)


schema = strawberry.Schema(query=Query)


graphql_app = GraphQL(schema)

app = FastAPI()
app.add_route("/graphql", graphql_app)
app.add_websocket_route("/graphql", graphql_app)

if __name__ == '__main__':
    uvicorn.run('main:app', host='localhost', port=8000, reload=True)

pip freeze:

anyio==3.6.1
asgiref==3.5.2
asyncpg==0.25.0
backports.cached-property==1.0.1
click==8.1.3
databases==0.6.0
fastapi==0.78.0
graphql-core==3.2.1
greenlet==1.1.2
h11==0.13.0
idna==3.3
psycopg2-binary==2.9.3
pydantic==1.9.1
Pygments==2.12.0
python-dateutil==2.8.2
python-multipart==0.0.5
six==1.16.0
sniffio==1.2.0
SQLAlchemy==1.4.37
starlette==0.19.1
strawberry-graphql==0.114.0
typing_extensions==4.2.0
uvicorn==0.17.6

aryadovoy avatar Jun 01 '22 18:06 aryadovoy

Looks like your GraphQL client was sending a 'OPTIONS' request. Was that intentional (usually one would use 'POST' requests to mutate and query data)? Most, if not all of our integrations don't support the HTTP 'OPTIONS' method. 👀

DoctorJohn avatar Jun 03 '22 11:06 DoctorJohn

Your Uvicorn server and whatever's serving the page you're making your GraphQL request from are on different ports, localhost:8000 and localhost:40288.

This causes the browser to send a CORS preflight request before sending the actual request. A preflight request is sent with the OPTIONS method, asking whether it's OK to send the request.

To have FastAPI handle the OPTIONS request, use the CORSMiddleware.

from fastapi.middleware.cors import CORSMiddleware

# ...

app = FastAPI()
app.add_middleware(
    CORSMiddleware, allow_headers=["*"], allow_origins=["http://localhost:40288"], allow_methods=["*"]
)

# ...

The strawberry serve command handles this by allowing all headers, origins and methods. https://github.com/strawberry-graphql/strawberry/blob/0.114.0/strawberry/cli/debug_server.py

Take a look at the FastAPI docs for more info: https://fastapi.tiangolo.com/tutorial/cors/

chrisberks avatar Jun 05 '22 11:06 chrisberks

Your Uvicorn server and whatever's serving the page you're making your GraphQL request from are on different ports, localhost:8000 and localhost:40288.

But second port is different every time. It works fine with allow_origins=["*"], but I'm not sure that this is good idea. :) I've tried with allow_origin_regex="https?://(localhost|127\.0\.0\.1):\d+." and it doesn't work.

Thanks for help!

aryadovoy avatar Jun 07 '22 10:06 aryadovoy

Looks like this issue is solved. Closing.

jkimbo avatar Oct 11 '22 14:10 jkimbo