Repository: mcollina/fastify-gql (js)

Issue:
Support for Content-Type: application/graphql
Add support for [application/graphql](https://graphql.org/learn/serving-over-http/#post-request) Content-Type. 

express-graphql already supports it, while appolo-server does not.

It is true, that GQL variables can not be passed as part of the query, but it becomes much easier to use in command line, automated tests and [benchmarks](https://github.com/the-benchmarker/graphql-benchmarks).



Pull request:
Add application/graphql support
PR closes #108.

Patch:
diff --git a/README.md b/README.md
index 329dc9a..4e99fcc 100644
--- a/README.md
+++ b/README.md
@@ -379,6 +379,21 @@ payload must conform to the following JSON schema:
 }
 ```
 
+For code from [example](#example) use:
+```sh
+curl -H "Content-Type:application/json" -XPOST -d '{"query": "query { add(x: 2, y: 2) }"}' http://localhost:3000/graphql
+```
+
+#### POST /graphql with Content-type: application/graphql
+
+Executes the GraphQL query or mutation described in the body. `operationName` and `variables` can not be passed using this method. The
+payload contains the GraphQL query.
+
+For code from [example](#example) use:
+```sh
+curl -H "Content-Type:application/graphql" -XPOST -d "query { add(x: 2, y: 2) }" http://localhost:3000/graphql
+```
+
 #### GET /graphiql
 
 Serves [GraphiQL](https://www.npmjs.com/package/graphiql) if enabled by
diff --git a/lib/routes.js b/lib/routes.js
index 317fc75..d7860b1 100644
--- a/lib/routes.js
+++ b/lib/routes.js
@@ -151,6 +151,15 @@ module.exports = async function (app, opts) {
     app.route(getOptions)
   }
 
+  app.addContentTypeParser('application/graphql', function (req, done) {
+    req.setEncoding('utf8')
+    var data = ''
+    req.on('data', chunk => { data += chunk })
+    req.on('end', _ => {
+      done(null, { query: data })
+    })
+  })
+
   app.post(graphqlPath, {
     schema: {
       body: {


Test patch:
diff --git a/test/routes.js b/test/routes.js
index d40f976..4661089 100644
--- a/test/routes.js
+++ b/test/routes.js
@@ -41,6 +41,40 @@ test('POST route', async (t) => {
   })
 })
 
+test('POST route application/graphql', async (t) => {
+  const app = Fastify()
+  const schema = `
+    type Query {
+      add(x: Int, y: Int): Int
+    }
+  `
+
+  const resolvers = {
+    add: async ({ x, y }) => x + y
+  }
+
+  app.register(GQL, {
+    schema,
+    resolvers
+  })
+
+  const query = '{ add(x: 2, y: 2) }'
+
+  const res = await app.inject({
+    method: 'POST',
+    headers: { 'content-type': 'application/graphql' },
+    url: '/graphql',
+    body: query
+  })
+
+  t.equal(res.statusCode, 200)
+  t.deepEqual(JSON.parse(res.body), {
+    data: {
+      add: 4
+    }
+  })
+})
+
 test('custom route', async (t) => {
   const app = Fastify()
   const schema = `
@@ -442,6 +476,49 @@ test('mutation with POST', async (t) => {
   t.equal(msg, 'hello world')
 })
 
+test('mutation with POST application/graphql', async (t) => {
+  const app = Fastify()
+  const schema = `
+    type Mutation {
+      setMessage(message: String): String
+    }
+
+    type Query {
+      getMessage: String
+    }
+  `
+
+  let msg = 'hello'
+  const resolvers = {
+    setMessage: async ({ message }) => {
+      msg = message
+      return message
+    },
+    async getMessage () { return msg }
+  }
+
+  app.register(GQL, {
+    schema,
+    resolvers
+  })
+
+  const query = 'mutation { setMessage(message: "hello world") }'
+
+  const res = await app.inject({
+    method: 'POST',
+    headers: { 'content-type': 'application/graphql' },
+    url: '/graphql',
+    body: query
+  })
+
+  t.deepEqual(JSON.parse(res.body), {
+    data: {
+      setMessage: 'hello world'
+    }
+  })
+  t.equal(msg, 'hello world')
+})
+
 test('mutation with GET errors', async (t) => {
   const app = Fastify()
   const schema = `