strawberry-graphql / strawberry

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

Unable to disable graphiql by graphql_ide=None #3327

Open shmoon-kr opened 10 months ago

shmoon-kr commented 10 months ago

Hi. I'm using strawberry graphql library for my project.

I'm using async view and I tried to disable graphql ide by giving a parameter like following.

` from strawberry.django.views import AsyncGraphQLView

class MyGraphQLView(AsyncGraphQLView): ...

urlpatterns = [ path("graphql/", MyGraphQLView.as_view(schema=schema, graphql_ide=None)), ]

`

But I still see graphiql is loaded when I accessed /graphql/ via GET method.

I looked into the details and I found that graphql_ide variable remains as a default value ("graphiql") in AsyncBaseHTTPView.run method.

` print(self.graphql_ide) # "graphiql was printed though I gave a parameter graphql_ide=None to AsyncGraphQLView.asView function. if self.should_render_graphql_ide(request_adapter): if self.graphql_ide: return await self.render_graphql_ide(request) else: raise HTTPException(404, "Not Found")

`

And I'm using subscription. So my asgi.py file is like following.

` urlpatterns = [re_path(r"graphql", GraphQLWSConsumer.as_asgi(schema=schema))]

gql_http_consumer = AuthMiddlewareStack(GraphQLHTTPConsumer.as_asgi(schema=schema)) gql_ws_consumer = GraphQLWSConsumer.as_asgi(schema=schema) app = ProtocolTypeRouter( { "http": URLRouter( [ re_path("^graphql", gql_http_consumer), re_path("^", django_asgi_app), ] ), "websocket": AuthMiddlewareStack(URLRouter(urlpatterns)) } )

`

System Information

Upvote & Fund

Fund with Polar

erikwrede commented 10 months ago

You can pass graphiql=False as a kwarg, but maybe we should improve the wording on this, since we now support other explorers 😊

patrick91 commented 10 months ago

@erikwrede maybe we should also support None?

shmoon-kr commented 10 months ago

Thanks for your attention and fast reply. I tried graphiql=False but I still failed.

But then I noticed an interesting phenomenon. When I run your suggestion (graphiql=False) with django debug server, (python ./manage.py runserver) it works correctly. But I run it in a production environment it doesn't work.

I'm serving it with a uvicorn thread under gunicorn. My command for a production environment is : gunicorn -k uvicorn.workers.UvicornWorker --workers 2 --threads 3 When I run the server with this command, graphiql=False parameter is ignored. I don't understand why.

I'm using django channels and I think this might have something to do with it.

Can you take a look at this one more time?

shmoon-kr commented 10 months ago

I found the solution by myself.

When I use channels, graphiql option should be given for GraphQLHTTPConsumer. The following worked for me. gql_http_consumer = AuthMiddlewareStack(GraphQLHTTPConsumer.as_asgi(schema=schema, graphql_ide=None))

Thanks.

erikwrede commented 10 months ago

Keeping this open as this seems like a good case for a DevX improvement. @patrick91 I think =None is also an option.

Birdi7 commented 6 months ago

Hello! I was wondering if I could fix this. However, with the following code snippet I see no graphiql_ide. Can you check if it's fixed by now?

My urls.py in django project

from django.urls import path

from strawberry.django.views import AsyncGraphQLView

import typing
import strawberry

@strawberry.type
class Book:
    title: str
    author: str

def get_books():
    return [
        Book(
            title="The Great Gatsby",
            author="F. Scott Fitzgerald",
        ),
    ]

@strawberry.type
class Query:
    books: typing.List[Book] = strawberry.field(resolver=get_books)

schema = strawberry.Schema(query=Query)

urlpatterns = [
    path("graphql/", AsyncGraphQLView.as_view(schema=schema,
                                         graphql_ide=None)),
]
patrick91 commented 6 months ago

@Birdi7 I don't think it has been fixed yet 😊

https://github.com/strawberry-graphql/strawberry/blob/main/strawberry/http/ides.py#L9-L30 we don't check for None here

Birdi7 commented 6 months ago

@patrick91 thank you for the entrypoint! here is what I've found. I still believe this is fixed. test function test_renders_graphiql_disabled from main branch checks the None value. https://github.com/strawberry-graphql/strawberry/blob/main/tests/http/test_graphql_ide.py#L73

How's it working? This code in SyncBaseHTTPView.run decides whether to call render_graphql_ide at all: https://github.com/strawberry-graphql/strawberry/blob/9500eab2c534c81fa099905cc64892ab37a3726d/strawberry/http/sync_base_view.py#L170 It's evaluated the same for both False and None values.

So, get_graphql_ide_html is not called at all, as the codeflow is SyncBaseHTTPView.run -> render_graphql_ide -> self.graphql_ide_html -> get_graphql_ide_html.