Closed jaydensmith closed 1 year ago
Do you use strawberry channels consumer? What is your setup?
@nrbnlulu yes I am using the GraphQLWSConsumer
and GraphQLHTTPConsumer
.
import os
from django.urls import re_path
from django.core.asgi import get_asgi_application
from gqlauth.core.middlewares import channels_jwt_middleware
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from strawberry.channels import GraphQLWSConsumer, GraphQLHTTPConsumer
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'franchiseportal.settings')
django_asgi_app = get_asgi_application()
from .schema import schema
application = ProtocolTypeRouter({
'http': URLRouter([
re_path('^graphql', AuthMiddlewareStack(channels_jwt_middleware(GraphQLHTTPConsumer.as_asgi(schema=schema)))),
re_path('^', django_asgi_app),
]),
'websocket': URLRouter([
re_path('^graphql', AuthMiddlewareStack(channels_jwt_middleware(GraphQLWSConsumer.as_asgi(schema=schema)))),
]),
})
Do you use JwtSchema
?
@nrbnlulu I wasn't, thanks for the pointer. Still not working, though, as ChannelsRequest
doesn't have a scope
attribute.
Note the line user_or_error: UserOrError = request.scope[USER_OR_ERROR_KEY]
.
@staticmethod
def _inject_user_and_errors(kwargs: dict) -> UserOrError:
context = kwargs.get("context_value")
# channels compat
if isinstance(context, dict):
request = context["request"]
user_or_error: UserOrError = request.scope[USER_OR_ERROR_KEY]
request.user = user_or_error.user # type: ignore
else:
user_or_error: UserOrError = getattr(context.request, USER_OR_ERROR_KEY) # type: ignore
context.request.user = user_or_error.user # type: ignore
return user_or_error
Weird... I have tests for channels... I'll dig into it later.
BTW what version of strawberry are you running?
@nrbnlulu the latest version, 0.195.2. It seems sometimes the request
variable is an instance of ChannelsRequest
, and sometimes it is the consumer. I haven't looked too deep but possibly the difference between a websocket connection and HTTP request.
Why would you use channels for http?
@nrbnlulu it's pretty typical to route traditional HTTP requests through ASGI? https://channels.readthedocs.io/en/stable/topics/routing.html
Yeah though you can just use django asgi app and have the grahpql view there, that middleware was created for channels ws requests only. django has it's own middleware. AFAIK this is the recommended way of doing this.
Hello, I have the same issue, I tried to do as in the examples but it doesn't work. When I do run it and visit /graphql, the GraphiQL keeps trying to fetch the schema and at the end it says error fetching schema and when I try to run any query or mutation whether it was mine or from gqlauth, the get_user fails and I get an error on USER_OR_ERROR...
This is asgi.py
from django.urls import re_path
from django.core.asgi import get_asgi_application
from gqlauth.core.middlewares import channels_jwt_middleware
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from strawberry.channels import GraphQLWSConsumer, GraphQLHTTPConsumer
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blajobers.settings')
django_asgi_app = get_asgi_application()
from .schema import arg_schema as schema
application = ProtocolTypeRouter({
'http': URLRouter([
re_path('^graphql', AuthMiddlewareStack(GraphQLHTTPConsumer.as_asgi(schema=schema))),
re_path('^', django_asgi_app),
]),
'websocket': URLRouter([
re_path('^graphql', AuthMiddlewareStack(channels_jwt_middleware(GraphQLWSConsumer.as_asgi(schema=schema)))),
]),
})
schema.py
import strawberry
from gqlauth.core.middlewares import JwtSchema
from gqlauth.user.queries import UserQueries
from users.schema import Query as UsersQueries
from gqlauth.user import arg_mutations as mutations
from services.schema import Query as ServiceQueries, Mutation as ServiceMutations
from tickets.schema import Query as TicketQueries, Mutation as TicketMutations
@strawberry.type
class Query(
UserQueries,
UsersQueries,
ServiceQueries,
TicketQueries
):
pass
@strawberry.type
class Mutation(
ServiceMutations,
TicketMutations,
):
# include what-ever mutations you want.
verify_token = mutations.VerifyToken.field
update_account = mutations.UpdateAccount.field
archive_account = mutations.ArchiveAccount.field
delete_account = mutations.DeleteAccount.field
password_change = mutations.PasswordChange.field
# swap_emails = mutations.SwapEmails.field
# captcha = Captcha.field
token_auth = mutations.ObtainJSONWebToken.field
register = mutations.Register.field
verify_account = mutations.VerifyAccount.field
resend_activation_email = mutations.ResendActivationEmail.field
send_password_reset_email = mutations.SendPasswordResetEmail.field
password_reset = mutations.PasswordReset.field
password_set = mutations.PasswordSet.field
refresh_token = mutations.RefreshToken.field
revoke_token = mutations.RevokeToken.field
# verify_secondary_email = mutations.VerifySecondaryEmail.field
arg_schema = JwtSchema(
query=Query,
mutation=Mutation
)
urls.py
from django.urls import path, include
from strawberry.django.views import AsyncGraphQLView, GraphQLView
from django.views.decorators.csrf import csrf_exempt
from .schema import arg_schema
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("admin/", admin.site.urls),
path("graphql/", csrf_exempt(GraphQLView.as_view(schema=arg_schema))),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The
ChannelsRequest
class has no attributeuser
. Fixed in my own project by changing to: