Carlo Schneider
Carlo Schneider

Reputation: 185

Get query/mutation operation name

How can I get the operation name in the context? In resolver I can get that with info parameter.

import { ApolloServer } from 'apollo-server'

const server = new ApolloServer({
  context: ({ req }) => {
    // Get query/mutation operation name like getAllUsers
  }
})

server.listen()

Upvotes: 10

Views: 10499

Answers (2)

NULL pointer
NULL pointer

Reputation: 1377

The req passed to context contains req.body.query, but when testing using PostMan to send GraphQL queries, I found my Apollo GraphQL server's req paramater does NOT contain the name of the query (even when I name it after the initial query declaration as Thomas Hennes correctly indicated above).

my req object DOES contain the req.body.variables, though.

To get the query name, I extract the first 40 characters from the body. You could parse this for the first { or ( or carriage return, but I just want to be able to see what the query/mutation is so this works for me:

context: async ({req, connection}) => {
      ...
      ...
      let query = null;
      // mutation or query, not a subscription:
      const bodyQuery = req.body && req.body.query;
      if (bodyQuery) {
        query = req.body.query.substring(0,40);
      } else {
        query='No query passed in req body';
      }
      let variables = null;
      if (req.body.variables) {
        variables = req.body.variables;
      }

Upvotes: 0

Thomas Hennes
Thomas Hennes

Reputation: 9939

Using the technique suggested in my comment, I was able to retrieve the operation name.

Let's say you have the following query:

query foo {
  baz {
    id
    name
  }
}

req.body has two keys that are relevant:

  1. req.body.query holds the entire query in a string format, with whitespaces and carriage returns preserved. While you can retrieve operation names from that string, it will require a bit of string manipulation ; namely, turning the string into an object, and then grabbing the root level key(s) (which can be multiple in case you trigger multiple operations within a single query). With the example above, this key will hold the following string: 'query foo {\n baz {\n id\n name\n }\n}'.

  2. req.body.operationName holds the name you gave your query, IF you named it. With the example above, this key will hold 'foo' (not 'baz' which is the name of the actual operation). You could however decide to exploit this facility by carefully naming your queries according to the operation they contain (this won't work if you trigger multiple ops within one query, however). If you do not name your query, this field holds null.

Edit: See How to parse GraphQL request string into an object here on SO for a way to turn the string retrieved in method 1 into a JS object and retrieve your actual operation name.

Further considerations:

Method 2 would really be appropriate for debugging purposes, for instance. Say you want to log variables for a specific query, you could name it and do the following:

const server = new ApolloServer({
  context: ({ req }) => {
    if (req.body.operationName === 'debugMe') {
      console.log(req.body.variables)
    }
  }
})

However, because Method 2 relies on the client naming the query, it cannot be used reliably for business logic purposes. Only Method 1 will correctly retrieve the operation name regardless of how the query is formed on the client side.

Upvotes: 6

Related Questions