ariadne
ariadne copied to clipboard
Document using ASGI middleware with Ariadne ASGI app
Ariadne ASGI app creates its own request on the way and loses all middleware as a side effect, ex. session information.
I think everything already works as intended, can we close this issue?
@patrys This works as intended, but internal feedback I've gathered so far is negative - people coming from Django expect to use Starlette's middleware to set things on request
, and then just access this request
from within resolver and have the data they've set on it.
If anything, we should at least document this as gotcha and present idiomatic alternatives (eg. resolving this data in context_value
factory).
Setting things on request works as intended, changes are reflected in scope
and picked up by the next request.
Ah, so those are available via request.scope
? All-right then!
I'll keep this issue open to see if it makes sense to mention this in our docs sometime when I'll be working on it.
Do you guys have a short tldr on how to do this?
Middlewares should use request.scope
instead of request
to store the data to be available from within the Ariadne. When people use Starlette's AuthenticationMiddleware
, they follow the docs and use info.context["request"].user
within resolvers, which fails because context["request"]
instance will be different request than one directly within Starlette. They should do info.context["request"].scope["user"]"
instead.
This is known gotcha, and something we should document.
Ok this is great to know! I installed starlette and created an AuthBackend and attempted to install the middleware inside of the ariadne middleware
But I'm still getting the following error
{
"data": null,
"errors": [
{
"message": "AuthenticationMiddleware must be installed to access request.auth",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"hello"
],
"extensions": {
"exception": {
"stacktrace": [
"Traceback (most recent call last):",
" File \"/graphql/execution/execute.py\", line 625, in resolve_field_value_or_error",
" result = resolve_fn(source, info, **args)",
" File \"server/api/schema.py\", line 13, in resolve_hello",
" print(request.auth)",
" File \"starlette/requests.py\", line 116, in auth",
" ), \"AuthenticationMiddleware must be installed to access request.auth\"",
"AssertionError: AuthenticationMiddleware must be installed to access request.auth"
],
"context": {
"self": "<starlette.re...t 0x10a4e3490>"
}
}
}
}
]
}
This is same thing. No middleware-specific attribute of request
will work within the resolver. You need to use info.context["request"].scope["auth"]
for this.
ASGI spec defines scope
as value that should be passable around layers of ASGI stack. If you see middleware that modifies request
directly but leaves scope
out, reach out to its author about this. Chances are the middleware may already be using scope and its only docs that could be updated (this is the case for Starlette).
To be clear, you only need to write changes to the request.scope
object, it's safe to read from the request
itself.
Any difference with uvcorn[standard] ?