gqlgen
gqlgen copied to clipboard
How to access the arguments of a query within the RequestContext Object ?
What happened?
Hi there,
When trying to obtain the variables from a request context Object (with graphql.GetRequestContext(ctx).Variables
with the following query:
query MyQuery {
queryNode(filter:{isRoot:true}) {
name
}
}
I obtain a empty map.
What did you expect?
map[filter: map[isRoot:true]]
Furthermore, I get the desired result if I use
query MyQuery($args: MyArgs!) {
queryNode(filter:$args) {
name
}
}
{ "args": {"isRoot": true}}
versions
- glqgen : v0.11.3
- go: 1.14.1
- gqlparser: v2/v2.0.1
Hop,
I apology, I think I misinterpreted the ctx.Variables
object semantic, and thus, in the example above, there is nothing abnormal when this field is empty because no variables (graphql data) was provided.
Thus, allows me to rephrase my issue as follow:
Is it possible to access the arguments of a query within the RequestContext Object ?
Is it possible to access the arguments of a query within the RequestContext Object ?
@dtrckd I did not do it from RequestContext
, instead of that from the 2nd input argument (in below example is input
)
func (r *mutationResolver) CreateContact(ctx context.Context, input model.NewContact) (*model.Contact, error) {
input NewContact {
firstName: String!
lastName: String!
accountId: String!
}
type Mutation {
createContact(input: NewContact!): Contact!
}
Tnaks @isuhendro. Yes I can access the input argument from the resolvers but the point is that I need to reconstruct th query as a bytes/string to re-send it to an other Graphql layer. I found it inappropriate to use those inputs because there are typed variable which I need to know before Marshalling them. The difficulties arise because I use a general interface share by several resolver to reconstruct the query, and checking/asserting the type everytimes although I do the same operation for all types which is: "reconstructing the query as a string".
I am currently using graphql.GetRequestContext(ctx).RawQuery
as a workaround bur I am not satisfied as I may need to modify the input query in the Business Logic Layer.
@dtrckd I have the same experience with parsing graphql.GetOperationContext(ctx).RawQuery
Feel like it is very tedious and error prone. Becomes more complex to deal with when there are multiple arguments/filter inputs in the resolvers and having this custom parser to keep up with schema updates is a nightmare.
@vektah it would be good to access the arguments from the operation context. Any plans to support this feature?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Nope, stale!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Nope, stale.
Will this issue get some love? Is there something that needs to be discussed? Something we can do to give it a little push?
Any updates on this? Running into the same issue with the newer graphql.GetOperationContext(ctx).Variables
Funny, I was lurking around this issue 30 second ago ! Do you guys think it would be a good idea to have access to the input as a map like we have for the variables, accessible for example through the requestContext object, i.e
graphql.Get(Request|Operation)Context(ctx).Inputs
?
I saw the merged PR for #2062. I'm curious has anyone implemented a logger with that yet?
I'm currently using:
// Implement query logger
srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
// Start timer
start := time.Now()
oc := graphql.GetOperationContext(ctx)
var query string
// Make sure this is not an IntrospectionQuery, we don't care about logging those
if !strings.Contains(oc.RawQuery, "IntrospectionQuery") {
query = oc.RawQuery
// Use : to make the queries easier to read
query = strings.Replace(query, " ", ":", -1)
query = strings.Replace(query, "\t", "", -1)
query = strings.Replace(query, "\n", "", -1)
}
gc, err := GinContextFromContext(ctx)
if err != nil {
zap.L().Error("unable to convert gql to gin context for flatquery", zap.Error(err))
}
oh := next(ctx)
jlogger.RequestLogEntry(start, query, gc, requestLogger)
return oh
})
which sort of works but the N+1 problem and spacing is not reliable.
here is RequestLogEntry in case someone else finds this useful with GIN as it was a bit of a pain.
// RequestLogEntry logs a gin HTTP request in JSON format, with some additional custom key/values
func RequestLogEntry(start time.Time, query string, c *gin.Context, requestLog *zap.Logger) {
// Process Request
c.Next()
// Stop timer
duration := GetDurationInMillseconds(start)
requestLog.Info("",
zap.String("client_ip", GetClientIP(c)),
zap.Float64("duration", duration),
zap.String("method", c.Request.Method),
zap.String("path", c.Request.RequestURI),
zap.Int("status", c.Writer.Status()),
zap.String("user_id", GetUserID(c)),
zap.String("referrer", c.Request.Referer()),
zap.String("user_agent", c.Request.Header.Get("User-Agent")),
zap.String("gql_query", query),
)
}