Question about handling actions on a per-request basis
timrs2998 opened this issue · comments
We've been struggling with how to do things on a "per request" basis. For example, we want to have a child logger created per request, forward headers found in a request, or setup a dataloader that is created for every request.
We're still on the old GrAMPS, not on 1.0 yet, but have always found performing these actions with GrAMPS to be awkward.
- logging: we create logger in middleware piece, but need "hacks" to get to the logger in
formatError
or to swap the logger used in the base connector. I'd really like to create another child logger for each data-source with the context name. - header forwarding: pass context.req.headers from resolver, through model, to the connector to pass headers through request-promise
- dataloader: hackery black magic
Do you have any insights into these use cases especially around forwarding headers and constructing dataloaders? It's been doable through hacks, but I'm wondering if the newer GrAMPS 1.0 makes these tasks any easier (less hacky).
Anything that needs to be done "per-request" should be done within context
In 1.0 a data-source provides either an Object
to use as context or a function that returns an Object
. The req
is provided to this function as its first argument.
const userloader = new DataLoader(...);
export const context = req => ({
headers: req.headers,
userloader,
});
These are then used in resolvers.
export const resolvers = {
Query: {
currentUser: (root, args, context) => context.userloader(context.headers.userId)
}
};
So looking at a data-source, https://github.com/gramps-graphql/data-source-xkcd/blob/master/src/index.js#L13 you're saying that this context
can be either a function or an object. I see the support for that in https://github.com/gramps-graphql/gramps/blob/master/src/gramps.js#L142 now.
That actually helps a lot, thanks!
@timrs2998 Also, I extracted the REST helpers (the model and connector) into a new package at https://github.com/gramps-graphql/rest-helpers — we can tackle the DataLoader issue there, because it should be creating a new instance per-request.
@ecwyne is correct about the header forwarding, but you can also do this from the gramps()
call instead of on a per-data source basis if you drop it into the extraContext
prop.
const GraphQLOptions = gramps({
dataSources: [/* ... */],
extraContext: req => ({
headers: req.headers,
}),
});