How do I manipulate the context at root field level but after the root field resolver runs
- Dominant language
- Go
- Stars
- 10.8k
- Forks
- 1.3k
- Avg merge
- 2d 36m
- Merged PRs (30d)
- 26
Description
### What happened?
I'm trying to inject a token into the golang context for each request, but only under certain condition based on the query. Because the token is only needed for loading certain GraphQL entities. On the other hand, I don't want to have this middleware to be applied using `AroundFields` either because if there are multiple such entities, i don't want to query the token multiple times which is expensive. i only want to query the token once.
So I wrote the following code and used `AroundRootFields`. But because this middleware runs before the `RootResolver` executes, `CollectFields` method will return me empty slice as nothing has been resolved.
```Go
srv.AroundRootFields(s.tokenMiddleware)
func (s *Server) tokenMiddleware(ctx context.Context, next graphql.RootResolver) graphql.Marshaler {
oc := graphql.GetOperationContext(ctx)
collected := graphql.CollectFieldsCtx(ctx, nil) // returns me empty slice
fields := getFieldsRecursively(
oc,
collected,
) // get back a slice of strings for the fields but this won't work
if !lo.Contains(fields, "specific_field_name") {
return next(oc)
}
token := s.getToken(ctx)
if token == nil {
return next(ctx)
}
return next(context.WithValue(ctx, "access_token", token))
}
```
### What did you expect?
Ideally I can have something like `PostRootResolverMiddleware` which executes **only once per root field** after root resolver runs but before passing context to the sub-field resolvers.
If this is not supported atm but shouldn't be too hard to implement, I can try putting out a PR too.
### Minimal graphql.schema and models to reproduce
### versions
- `go run github.com/99designs/gqlgen version`? `v0.17.26`
- `go version`? `1.20`
Contributor guide
Assessment
This issue has not been assessed yet.