-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling context function with WebSocket connection parameters creates confusion; either docs or API need improvement #2315
Comments
Thanks so much for the incredibly thorough description! From a purely API-design POV (technical limitations aside), my initial instinct is to avoid adding to the surface area of the ApolloServer constructor's API if possible. Would it make sense to think of E.g. const server = new ApolloServer({
schema,
context: ({ req, connection }) => {
if (connection) {
return getContextFromSubscription(connection);
}
return getContextFromHttpRequest(req);
},
}); where const getContextFromHttpRequest = ({ req }: { req: $Request }): Params => {
const auth = req.get('authorization')
const match = /^Bearer (.*)$/i.exec(auth || '')
const authToken = match ? match[1] : null
return {
authToken,
user: await getUserByToken(null, authToken)),
}
} What do you think? |
Its working for me. |
@cheapsteak yeah what you propose is probably a lot easier to understand, I don't know what I was thinking with what I proposed. To summarize, FWIW taking multiple argument types isn't the defining characteristic of a reducer...the name "reducer" comes from the fact that |
came here trying to figure out how to get the subscription context passed and I found a lot of users doing something like |
Apollo Server 3 no longer has a superficial built-in subscriptions integration, so I'm closing this issue. If you choose to integration AS3 with |
I'll be happy to make a PR to clean up the API or improve the documentation after discussing the best solution to this with folks.
Looking at the code example in https://www.apollographql.com/docs/apollo-server/v2/features/authentication.html#context, it looks like
context
will always be called with thereq
andres
from the HTTP middleware:However, this is not so. As soon as one starts using subscriptions, they get a rude awakening (Issue #1537): now
context
is called with the WebSocket connection, and they get the errorCannot read property 'headers' of undefined
when they try to readreq.headers
.It was only after thoroughly debugging this issue and seeing what was happening under the hood that I managed to find the docs that actually show a grand unified context function: https://www.apollographql.com/docs/apollo-server/v2/features/subscriptions.html#Context-with-Subscriptions
But since it's called in two completely different ways, and the code paths for the two are entirely separated (here at least), I don't think it was a very good candidate for unification.
Adding to the confusion is the fact that subscription params have to be accessed from a separate
subscriptions.onConnect
function which is completely missing from the above example. Clearly I'm not the only one who was confused by the interplay between these two functions; others were also surprised that the context returned fromonConnect
can get blown away if not all of its properties are returned from thecontext
function (#1597).The example of
onConnect
I found in the docs makes it look like the single source of truth for subscription context. Notice how it is not just extracting values fromconnectionParams
; it's also computing derived context props, which it seems like thecontext
function is supposed to be responsible for:It seems like the intended use of the API is actually something like:
But I would argue that we should either
subscriptions.onConnect
and callcontext
withconnectionParams
directlycontext
for subscriptions at all, and rely solely onsubscriptions.onConnect
to get the contextcontext
function,subscriptions.onConnect
, and how they relate a lot more thoroughly, for example:req
may be undefined in the case that the function is called for a subscriptions WebSocketonConnect
docs that its return value is passed to the context function asconnection.context
and must be returned intact to avoid losing any propertiesonConnect
function to the example in the "Context with Subscriptions" docscc @samalexander, @arist0tl3, @sabith-th, @jbaxleyiii, @evans
Personally, I think it would be best to have one function in charge of extracting params from the request, one function in charge of extracting params from the websocket connection, and one function that takes params and returns the context. Here is how that would look:
The text was updated successfully, but these errors were encountered: