{"id":13880670,"url":"https://github.com/graphql/graphql-http","last_synced_at":"2025-10-03T19:58:23.378Z","repository":{"id":52192728,"uuid":"492820089","full_name":"graphql/graphql-http","owner":"graphql","description":"Simple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.","archived":false,"fork":false,"pushed_at":"2025-06-23T13:09:44.000Z","size":9882,"stargazers_count":351,"open_issues_count":8,"forks_count":29,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-09-26T07:08:43.527Z","etag":null,"topics":["apollo","client","express","fastify","graphql","http","observables","relay","server","the-guild","transport"],"latest_commit_sha":null,"homepage":"https://graphql-http.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graphql.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"enisdenjo"}},"created_at":"2022-05-16T12:13:17.000Z","updated_at":"2025-09-14T17:55:46.000Z","dependencies_parsed_at":"2023-11-22T22:26:02.088Z","dependency_job_id":"495b7d34-213f-4b81-9d13-43bf1caa806b","html_url":"https://github.com/graphql/graphql-http","commit_stats":{"total_commits":294,"total_committers":11,"mean_commits":"26.727272727272727","dds":0.173469387755102,"last_synced_commit":"cd6d6cf20c57f9d992b60684c477230a5f05a780"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/graphql/graphql-http","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql%2Fgraphql-http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql%2Fgraphql-http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql%2Fgraphql-http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql%2Fgraphql-http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graphql","download_url":"https://codeload.github.com/graphql/graphql-http/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql%2Fgraphql-http/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277184126,"owners_count":25775285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-27T02:00:08.978Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apollo","client","express","fastify","graphql","http","observables","relay","server","the-guild","transport"],"created_at":"2024-08-06T08:03:22.319Z","updated_at":"2025-10-03T19:58:23.326Z","avatar_url":"https://github.com/graphql.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cbr /\u003e\n\n  \u003ch3\u003egraphql-http\u003c/h3\u003e\n\n  \u003ch6\u003eSimple, pluggable, zero-dependency, \u003ca href=\"https://graphql.github.io/graphql-over-http\"\u003eGraphQL over HTTP spec\u003c/a\u003e compliant server, client and audit suite.\u003c/h6\u003e\n\n[![CI](https://github.com/graphql/graphql-http/workflows/CI/badge.svg)](https://github.com/graphql/graphql-http/actions?query=workflow%3A%22Continuous+integration%22) [![graphql-http](https://img.shields.io/npm/v/graphql-http.svg?label=graphql-http\u0026logo=npm)](https://www.npmjs.com/package/graphql-http)\n\n\u003ci\u003eQuickly check for compliance? Visit \u003cb\u003e[graphql-http.com](https://graphql-http.com)\u003c/b\u003e!\u003c/i\u003e\n\n\u003ci\u003eWant a full-featured server? See the \u003cb\u003e[servers section](#servers)\u003c/b\u003e!\u003c/i\u003e\n\n\u003ci\u003eNeed subscriptions? Try \u003cb\u003e[graphql-ws](https://github.com/enisdenjo/graphql-ws)\u003c/b\u003e or \u003cb\u003e[graphql-sse](https://github.com/enisdenjo/graphql-sse)\u003c/b\u003e instead!\u003c/i\u003e\n\n  \u003cbr /\u003e\n\u003c/div\u003e\n\n## Getting started\n\n#### Install\n\n```shell\nyarn add graphql-http\n```\n\n#### Create a GraphQL schema\n\n```js\nimport { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';\n\n/**\n * Construct a GraphQL schema and define the necessary resolvers.\n *\n * type Query {\n *   hello: String\n * }\n */\nconst schema = new GraphQLSchema({\n  query: new GraphQLObjectType({\n    name: 'Query',\n    fields: {\n      hello: {\n        type: GraphQLString,\n        resolve: () =\u003e 'world',\n      },\n    },\n  }),\n});\n```\n\n#### Start the server\n\n##### With [`http`](https://nodejs.org/api/http.html)\n\n```js\nimport http from 'http';\nimport { createHandler } from 'graphql-http/lib/use/http';\nimport { schema } from './previous-step';\n\n// Create the GraphQL over HTTP Node request handler\nconst handler = createHandler({ schema });\n\n// Create a HTTP server using the listener on `/graphql`\nconst server = http.createServer((req, res) =\u003e {\n  if (req.url.startsWith('/graphql')) {\n    handler(req, res);\n  } else {\n    res.writeHead(404).end();\n  }\n});\n\nserver.listen(4000);\nconsole.log('Listening to port 4000');\n```\n\n##### With [`http2`](https://nodejs.org/api/http2.html)\n\n_Browsers might complain about self-signed SSL/TLS certificates. [Help can be found on StackOverflow.](https://stackoverflow.com/questions/7580508/getting-chrome-to-accept-self-signed-localhost-certificate)_\n\n```shell\n$ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \\\n  -keyout localhost-privkey.pem -out localhost-cert.pem\n```\n\n```js\nimport fs from 'fs';\nimport http2 from 'http2';\nimport { createHandler } from 'graphql-http/lib/use/http2';\nimport { schema } from './previous-step';\n\n// Create the GraphQL over HTTP Node request handler\nconst handler = createHandler({ schema });\n\n// Create a HTTP/2 server using the handler on `/graphql`\nconst server = http2.createSecureServer(\n  {\n    key: fs.readFileSync('localhost-privkey.pem'),\n    cert: fs.readFileSync('localhost-cert.pem'),\n  },\n  (req, res) =\u003e {\n    if (req.url.startsWith('/graphql')) {\n      handler(req, res);\n    } else {\n      res.writeHead(404).end();\n    }\n  },\n);\n\nserver.listen(4000);\nconsole.log('Listening to port 4000');\n```\n\n##### With [`express`](https://expressjs.com/)\n\n```js\nimport express from 'express'; // yarn add express\nimport { createHandler } from 'graphql-http/lib/use/express';\nimport { schema } from './previous-step';\n\n// Create an express instance serving all methods on `/graphql`\n// where the GraphQL over HTTP express request handler is\nconst app = express();\napp.all('/graphql', createHandler({ schema }));\n\napp.listen({ port: 4000 });\nconsole.log('Listening to port 4000');\n```\n\n##### With [`fastify`](https://www.fastify.io/)\n\n```js\nimport Fastify from 'fastify'; // yarn add fastify\nimport { createHandler } from 'graphql-http/lib/use/fastify';\nimport { schema } from './previous-step';\n\n// Create a fastify instance serving all methods on `/graphql`\n// where the GraphQL over HTTP fastify request handler is\nconst fastify = Fastify();\nfastify.all('/graphql', createHandler({ schema }));\n\nfastify.listen({ port: 4000 });\nconsole.log('Listening to port 4000');\n```\n\n##### With [`Koa`](https://koajs.com/)\n\n```js\nimport Koa from 'koa'; // yarn add koa\nimport mount from 'koa-mount'; // yarn add koa-mount\nimport { createHandler } from 'graphql-http/lib/use/koa';\nimport { schema } from './previous-step';\n\nconst app = new Koa();\napp.use(mount('/graphql', createHandler({ schema })));\n\napp.listen({ port: 4000 });\nconsole.log('Listening to port 4000');\n```\n\n##### With [`uWebSockets.js`](https://github.com/uNetworking/uWebSockets.js)\n\n```js\nimport uWS from 'uWebSockets.js'; // yarn add uWebSockets.js@uNetworking/uWebSockets.js#\u003cversion\u003e\nimport { createHandler } from 'graphql-http/lib/use/uWebSockets';\nimport { schema } from './previous-step';\n\nuWS\n  .App()\n  .any('/graphql', createHandler({ schema }))\n  .listen(4000, () =\u003e {\n    console.log('Listening to port 4000');\n  });\n```\n\n##### With [`Deno`](https://deno.land/)\n\n```ts\nimport { serve } from 'https://deno.land/std@0.151.0/http/server.ts';\nimport { createHandler } from 'https://esm.sh/graphql-http/lib/use/fetch';\nimport { schema } from './previous-step';\n\n// Create the GraphQL over HTTP native fetch handler\nconst handler = createHandler({ schema });\n\n// Start serving on `/graphql` using the handler\nawait serve(\n  (req: Request) =\u003e {\n    const [path, _search] = req.url.split('?');\n    if (path.endsWith('/graphql')) {\n      return handler(req);\n    } else {\n      return new Response(null, { status: 404 });\n    }\n  },\n  {\n    port: 4000, // Listening to port 4000\n  },\n);\n```\n\n##### With [`Bun`](https://bun.sh/)\n\n```js\nimport { createHandler } from 'graphql-http/lib/use/fetch'; // bun install graphql-http\nimport { schema } from './previous-step';\n\n// Create the GraphQL over HTTP native fetch handler\nconst handler = createHandler({ schema });\n\n// Start serving on `/graphql` using the handler\nexport default {\n  port: 4000, // Listening to port 4000\n  fetch(req) {\n    const [path, _search] = req.url.split('?');\n    if (path.endsWith('/graphql')) {\n      return handler(req);\n    } else {\n      return new Response(null, { status: 404 });\n    }\n  },\n};\n```\n\n##### With [`Netlify Functions`](https://docs.netlify.com/functions/overview/)\n\n```js\nimport { createHandler } from 'graphql-http/lib/use/@netlify/functions'; // yarn add @netlify/functions\nimport { schema } from './previous-step';\n\n// Create the GraphQL over HTTP native fetch handler\nexport const handler = createHandler({ schema });\n```\n\n#### Use the client\n\n```js\nimport { createClient } from 'graphql-http';\n\nconst client = createClient({\n  url: 'http://localhost:4000/graphql',\n});\n\n(async () =\u003e {\n  let cancel = () =\u003e {\n    /* abort the request if it is in-flight */\n  };\n\n  const result = await new Promise((resolve, reject) =\u003e {\n    let result;\n    cancel = client.subscribe(\n      {\n        query: '{ hello }',\n      },\n      {\n        next: (data) =\u003e (result = data),\n        error: reject,\n        complete: () =\u003e resolve(result),\n      },\n    );\n  });\n\n  expect(result).toEqual({ hello: 'world' });\n})();\n```\n\n#### Serve [GraphiQL](https://github.com/graphql/graphiql)\n\nThanks to [`ruru`](https://github.com/graphile/crystal/tree/main/grafast/ruru), serving GraphiQL is as easy as running:\n\n```sh\nnpx ruru -SP -p 4001 -e http://localhost:4000/graphql\n```\n\nOpen [http://localhost:4001](http://localhost:4001) in the browser to use it.\n\n## Recipes\n\n\u003cdetails id=\"promise\"\u003e\n\u003csummary\u003e\u003ca href=\"#promise\"\u003e🔗\u003c/a\u003e Client usage with Promise\u003c/summary\u003e\n\n```ts\nimport { ExecutionResult } from 'graphql';\nimport { createClient, RequestParams } from 'graphql-http';\nimport { getSession } from './my-auth';\n\nconst client = createClient({\n  url: 'http://hey.there:4000/graphql',\n  headers: async () =\u003e {\n    const session = await getSession();\n    if (session) {\n      return {\n        Authorization: `Bearer ${session.token}`,\n      };\n    }\n  },\n});\n\nfunction execute\u003cData, Extensions\u003e(\n  params: RequestParams,\n): [request: Promise\u003cExecutionResult\u003cData, Extensions\u003e\u003e, cancel: () =\u003e void] {\n  let cancel!: () =\u003e void;\n  const request = new Promise\u003cExecutionResult\u003cData, Extensions\u003e\u003e(\n    (resolve, reject) =\u003e {\n      let result: ExecutionResult\u003cData, Extensions\u003e;\n      cancel = client.subscribe\u003cData, Extensions\u003e(params, {\n        next: (data) =\u003e (result = data),\n        error: reject,\n        complete: () =\u003e resolve(result),\n      });\n    },\n  );\n  return [request, cancel];\n}\n\n(async () =\u003e {\n  const [request, cancel] = execute({\n    query: '{ hello }',\n  });\n\n  // just an example, not a real function\n  onUserLeavePage(() =\u003e {\n    cancel();\n  });\n\n  const result = await request;\n\n  expect(result).toBe({ data: { hello: 'world' } });\n})();\n```\n\n\u003c/details\u003e\n\n\u003c/details\u003e\n\n\u003cdetails id=\"observable\"\u003e\n\u003csummary\u003e\u003ca href=\"#observable\"\u003e🔗\u003c/a\u003e Client usage with \u003ca href=\"https://github.com/tc39/proposal-observable\"\u003eObservable\u003c/a\u003e\u003c/summary\u003e\n\n```js\nimport { Observable } from 'relay-runtime';\n// or\nimport { Observable } from '@apollo/client/core';\n// or\nimport { Observable } from 'rxjs';\n// or\nimport Observable from 'zen-observable';\n// or any other lib which implements Observables as per the ECMAScript proposal: https://github.com/tc39/proposal-observable\nimport { createClient } from 'graphql-http';\nimport { getSession } from './my-auth';\n\nconst client = createClient({\n  url: 'http://graphql.loves:4000/observables',\n  headers: async () =\u003e {\n    const session = await getSession();\n    if (session) {\n      return {\n        Authorization: `Bearer ${session.token}`,\n      };\n    }\n  },\n});\n\nconst observable = new Observable((observer) =\u003e\n  client.subscribe({ query: '{ hello }' }, observer),\n);\n\nconst subscription = observable.subscribe({\n  next: (result) =\u003e {\n    expect(result).toBe({ data: { hello: 'world' } });\n  },\n});\n\n// unsubscribe will cancel the request if it is pending\nsubscription.unsubscribe();\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"relay\"\u003e\n\u003csummary\u003e\u003ca href=\"#relay\"\u003e🔗\u003c/a\u003e Client usage with \u003ca href=\"https://relay.dev\"\u003eRelay\u003c/a\u003e\u003c/summary\u003e\n\n```ts\nimport { GraphQLError } from 'graphql';\nimport {\n  Network,\n  Observable,\n  RequestParameters,\n  Variables,\n} from 'relay-runtime';\nimport { createClient } from 'graphql-http';\nimport { getSession } from './my-auth';\n\nconst client = createClient({\n  url: 'http://i.love:4000/graphql',\n  headers: async () =\u003e {\n    const session = await getSession();\n    if (session) {\n      return {\n        Authorization: `Bearer ${session.token}`,\n      };\n    }\n  },\n});\n\nfunction fetch(operation: RequestParameters, variables: Variables) {\n  return Observable.create((sink) =\u003e {\n    if (!operation.text) {\n      return sink.error(new Error('Operation text cannot be empty'));\n    }\n    return client.subscribe(\n      {\n        operationName: operation.name,\n        query: operation.text,\n        variables,\n      },\n      sink,\n    );\n  });\n}\n\nexport const network = Network.create(fetch);\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"apollo-client\"\u003e\n\u003csummary\u003e\u003ca href=\"#apollo-client\"\u003e🔗\u003c/a\u003e Client usage with \u003ca href=\"https://www.apollographql.com\"\u003eApollo\u003c/a\u003e\u003c/summary\u003e\n\n```ts\nimport {\n  ApolloLink,\n  Operation,\n  FetchResult,\n  Observable,\n} from '@apollo/client/core';\nimport { print, GraphQLError } from 'graphql';\nimport { createClient, ClientOptions, Client } from 'graphql-http';\nimport { getSession } from './my-auth';\n\nclass HTTPLink extends ApolloLink {\n  private client: Client;\n\n  constructor(options: ClientOptions) {\n    super();\n    this.client = createClient(options);\n  }\n\n  public request(operation: Operation): Observable\u003cFetchResult\u003e {\n    return new Observable((sink) =\u003e {\n      return this.client.subscribe\u003cFetchResult\u003e(\n        { ...operation, query: print(operation.query) },\n        {\n          next: sink.next.bind(sink),\n          complete: sink.complete.bind(sink),\n          error: sink.error.bind(sink),\n        },\n      );\n    });\n  }\n}\n\nconst link = new HTTPLink({\n  url: 'http://where.is:4000/graphql',\n  headers: async () =\u003e {\n    const session = await getSession();\n    if (session) {\n      return {\n        Authorization: `Bearer ${session.token}`,\n      };\n    }\n  },\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"request-retries\"\u003e\n\u003csummary\u003e\u003ca href=\"#request-retries\"\u003e🔗\u003c/a\u003e Client usage with request retries\u003c/summary\u003e\n\n```ts\nimport { createClient, NetworkError } from 'graphql-http';\n\nconst client = createClient({\n  url: 'http://unstable.service:4000/graphql',\n  shouldRetry: async (err: NetworkError, retries: number) =\u003e {\n    if (retries \u003e 3) {\n      // max 3 retries and then report service down\n      return false;\n    }\n\n    // try again when service unavailable, could be temporary\n    if (err.response?.status === 503) {\n      // wait one second (you can alternatively time the promise resolution to your preference)\n      await new Promise((resolve) =\u003e setTimeout(resolve, 1000));\n      return true;\n    }\n\n    // otherwise report error immediately\n    return false;\n  },\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"browser\"\u003e\n\u003csummary\u003e\u003ca href=\"#browser\"\u003e🔗\u003c/a\u003e Client usage in browser\u003c/summary\u003e\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003ctitle\u003eGraphQL over HTTP\u003c/title\u003e\n    \u003cscript\n      type=\"text/javascript\"\n      src=\"https://unpkg.com/graphql-http/umd/graphql-http.min.js\"\n    \u003e\u003c/script\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cscript type=\"text/javascript\"\u003e\n      const client = graphqlHttp.createClient({\n        url: 'http://umdfor.the:4000/win/graphql',\n      });\n\n      // consider other recipes for usage inspiration\n    \u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"node-client\"\u003e\n\u003csummary\u003e\u003ca href=\"#node-client\"\u003e🔗\u003c/a\u003e Client usage in Node\u003c/summary\u003e\n\n```js\nconst fetch = require('node-fetch'); // yarn add node-fetch\nconst { AbortController } = require('node-abort-controller'); // (node \u003c v15) yarn add node-abort-controller\nconst { createClient } = require('graphql-http');\n\nconst client = createClient({\n  url: 'http://no.browser:4000/graphql',\n  fetchFn: fetch,\n  abortControllerImpl: AbortController, // node \u003c v15\n});\n\n// consider other recipes for usage inspiration\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"deno-client\"\u003e\n\u003csummary\u003e\u003ca href=\"#deno-client\"\u003e🔗\u003c/a\u003e Client usage in Deno\u003c/summary\u003e\n\n```js\nimport { createClient } from 'https://esm.sh/graphql-http';\n\nconst client = createClient({\n  url: 'http://deno.earth:4000/graphql',\n});\n\n// consider other recipes for usage inspiration\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"bun-client\"\u003e\n\u003csummary\u003e\u003ca href=\"#bun-client\"\u003e🔗\u003c/a\u003e Client usage in Bun\u003c/summary\u003e\n\n```js\nimport { createClient } from 'graphql-http'; // bun install graphql-http\n\nconst client = createClient({\n  url: 'http://bun.bread:4000/graphql',\n});\n\n// consider other recipes for usage inspiration\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"migrating-express-graphql\"\u003e\n\u003csummary\u003e\u003ca href=\"#migrating-express-graphql\"\u003e🔗\u003c/a\u003e Server handler migration from \u003ca href=\"https://github.com/graphql/express-graphql\"\u003eexpress-graphql\u003c/a\u003e\u003c/summary\u003e\n\n```diff\nimport express from 'express';\nimport { schema } from './my-graphql-schema';\n\n-import { graphqlHTTP } from 'express-graphql';\n+import { createHandler } from 'graphql-http/lib/use/express';\n\nconst app = express();\n\napp.use(\n  '/graphql',\n-  graphqlHTTP({ schema }),\n+  createHandler({ schema }),\n);\n\napp.listen(4000);\n```\n\n\u003c/details\u003e\n\u003cdetails id=\"auth\"\u003e\n\u003csummary\u003e\u003ca href=\"#auth\"\u003e🔗\u003c/a\u003e Server handler usage with authentication\u003c/summary\u003e\n\nAuthenticate the user within `graphql-http` during GraphQL execution context assembly. This is a approach is less safe compared to early authentication ([see early authentication in Node](#auth-node-early)) because some GraphQL preparations or operations are executed even if the user is not unauthorized.\n\n```js\nimport { createHandler } from 'graphql-http';\nimport {\n  schema,\n  getUserFromCookies,\n  getUserFromAuthorizationHeader,\n} from './my-graphql';\n\nconst handler = createHandler({\n  schema,\n  context: async (req) =\u003e {\n    // process token, authenticate user and attach it to your graphql context\n    const userId = await getUserFromCookies(req.headers.cookie);\n    // or\n    const userId = await getUserFromAuthorizationHeader(\n      req.headers.authorization,\n    );\n\n    // respond with 401 if the user was not authenticated\n    if (!userId) {\n      return [null, { status: 401, statusText: 'Unauthorized' }];\n    }\n\n    // otherwise attach the user to the graphql context\n    return { userId };\n  },\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"context\"\u003e\n\u003csummary\u003e\u003ca href=\"#context\"\u003e🔗\u003c/a\u003e Server handler usage with custom context value\u003c/summary\u003e\n\n```js\nimport { createHandler } from 'graphql-http';\nimport { schema, getDynamicContext } from './my-graphql';\n\nconst handler = createHandler({\n  schema,\n  context: async (req, args) =\u003e {\n    return getDynamicContext(req, args);\n  },\n  // or static context by supplying the value directly\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"custom-exec\"\u003e\n\u003csummary\u003e\u003ca href=\"#custom-exec\"\u003e🔗\u003c/a\u003e Server handler usage with custom execution arguments\u003c/summary\u003e\n\n```js\nimport { parse } from 'graphql';\nimport { createHandler } from 'graphql-http';\nimport { getSchemaForRequest, myValidationRules } from './my-graphql';\n\nconst handler = createHandler({\n  onSubscribe: async (req, params) =\u003e {\n    const schema = await getSchemaForRequest(req);\n\n    const args = {\n      schema,\n      operationName: params.operationName,\n      document: parse(params.query),\n      variableValues: params.variables,\n    };\n\n    return args;\n  },\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"auth-node-early\"\u003e\n\u003csummary\u003e\u003ca href=\"#auth-node-early\"\u003e🔗\u003c/a\u003e Server handler usage in Node with early authentication (recommended)\u003c/summary\u003e\n\nAuthenticate the user early, before reaching `graphql-http`. This is the recommended approach because no GraphQL preparations or operations are executed if the user is not authorized.\n\n```js\nimport { createHandler } from 'graphql-http';\nimport {\n  schema,\n  getUserFromCookies,\n  getUserFromAuthorizationHeader,\n} from './my-graphql';\n\nconst handler = createHandler({\n  schema,\n  context: async (req) =\u003e {\n    // user is authenticated early (see below), simply attach it to the graphql context\n    return { userId: req.raw.userId };\n  },\n});\n\nconst server = http.createServer(async (req, res) =\u003e {\n  if (!req.url.startsWith('/graphql')) {\n    return res.writeHead(404).end();\n  }\n\n  try {\n    // process token, authenticate user and attach it to the request\n    req.userId = await getUserFromCookies(req.headers.cookie);\n    // or\n    req.userId = await getUserFromAuthorizationHeader(\n      req.headers.authorization,\n    );\n\n    // respond with 401 if the user was not authenticated\n    if (!req.userId) {\n      return res.writeHead(401, 'Unauthorized').end();\n    }\n\n    const [body, init] = await handler({\n      url: req.url,\n      method: req.method,\n      headers: req.headers,\n      body: () =\u003e\n        new Promise((resolve) =\u003e {\n          let body = '';\n          req.on('data', (chunk) =\u003e (body += chunk));\n          req.on('end', () =\u003e resolve(body));\n        }),\n      raw: req,\n    });\n    res.writeHead(init.status, init.statusText, init.headers).end(body);\n  } catch (err) {\n    res.writeHead(500).end(err.message);\n  }\n});\n\nserver.listen(4000);\nconsole.log('Listening to port 4000');\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"graphql-upload-http\"\u003e\n\u003csummary\u003e\u003ca href=\"#graphql-upload-http\"\u003e🔗\u003c/a\u003e Server handler usage with \u003ca href=\"https://github.com/jaydenseric/graphql-upload\"\u003egraphql-upload\u003c/a\u003e and \u003ca href=\"https://nodejs.org/api/http.html\"\u003ehttp\u003c/a\u003e\u003c/summary\u003e\n\n```js\nimport http from 'http';\nimport { createHandler } from 'graphql-http/lib/use/http';\nimport processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload\nimport { schema } from './my-graphql';\n\nconst handler = createHandler({\n  schema,\n  async parseRequestParams(req) {\n    const params = await processRequest(req.raw, req.context.res);\n    if (Array.isArray(params)) {\n      throw new Error('Batching is not supported');\n    }\n    return {\n      ...params,\n      // variables must be an object as per the GraphQL over HTTP spec\n      variables: Object(params.variables),\n    };\n  },\n});\n\nconst server = http.createServer((req, res) =\u003e {\n  if (req.url.startsWith('/graphql')) {\n    handler(req, res);\n  } else {\n    res.writeHead(404).end();\n  }\n});\n\nserver.listen(4000);\nconsole.log('Listening to port 4000');\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"graphql-upload-express\"\u003e\n\u003csummary\u003e\u003ca href=\"#graphql-upload-express\"\u003e🔗\u003c/a\u003e Server handler usage with \u003ca href=\"https://github.com/jaydenseric/graphql-upload\"\u003egraphql-upload\u003c/a\u003e and \u003ca href=\"https://expressjs.com/\"\u003eexpress\u003c/a\u003e\u003c/summary\u003e\n\n```js\nimport express from 'express'; // yarn add express\nimport { createHandler } from 'graphql-http/lib/use/express';\nimport processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload\nimport { schema } from './my-graphql';\n\nconst app = express();\napp.all(\n  '/graphql',\n  createHandler({\n    schema,\n    async parseRequestParams(req) {\n      const params = await processRequest(req.raw, req.context.res);\n      if (Array.isArray(params)) {\n        throw new Error('Batching is not supported');\n      }\n      return {\n        ...params,\n        // variables must be an object as per the GraphQL over HTTP spec\n        variables: Object(params.variables),\n      };\n    },\n  }),\n);\n\napp.listen({ port: 4000 });\nconsole.log('Listening to port 4000');\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"audit-jest\"\u003e\n\u003csummary\u003e\u003ca href=\"#audit-jest\"\u003e🔗\u003c/a\u003e Audit for servers usage in \u003ca href=\"https://jestjs.io\"\u003eJest\u003c/a\u003e environment\u003c/summary\u003e\n\n```js\nimport { fetch } from '@whatwg-node/fetch';\nimport { serverAudits } from 'graphql-http';\n\nfor (const audit of serverAudits({\n  url: 'http://localhost:4000/graphql',\n  fetchFn: fetch,\n})) {\n  test(audit.name, async () =\u003e {\n    const result = await audit.fn();\n    if (result.status === 'error') {\n      throw result.reason;\n    }\n    if (result.status === 'warn') {\n      console.warn(result.reason); // or throw if you want full compliance (warnings are not requirements)\n    }\n    // result.status === 'ok'\n  });\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"audit-deno\"\u003e\n\u003csummary\u003e\u003ca href=\"#audit-deno\"\u003e🔗\u003c/a\u003e Audit for servers usage in \u003ca href=\"https://deno.land\"\u003eDeno\u003c/a\u003e environment\u003c/summary\u003e\n\n```ts\nimport { serverAudits } from 'npm:graphql-http';\n\nfor (const audit of serverAudits({\n  url: 'http://localhost:4000/graphql',\n  fetchFn: fetch,\n})) {\n  Deno.test(audit.name, async () =\u003e {\n    const result = await audit.fn();\n    if (result.status === 'error') {\n      throw result.reason;\n    }\n    if (result.status === 'warn') {\n      console.warn(result.reason); // or throw if you want full compliance (warnings are not requirements)\n    }\n    // Avoid leaking resources\n    if ('body' in result \u0026\u0026 result.body instanceof ReadableStream) {\n      await result.body.cancel();\n    }\n  });\n}\n```\n\nPut the above contents in a file and run it with `deno test --allow-net`.\n\n\u003c/details\u003e\n\n## Only [GraphQL over HTTP](https://graphql.github.io/graphql-over-http/)\n\nThis is the official [GraphQL over HTTP spec](https://graphql.github.io/graphql-over-http/) reference implementation and as such follows the specification strictly without any additional features (like playgrounds or GUIs, file uploads, @stream/@defer directives and subscriptions).\n\nHaving said this, graphql-http is mostly aimed for library authors and simple server setups, where the requirements are exact to what the aforementioned spec offers.\n\n## [Servers](/implementations)\n\nIf you want a feature-full server with bleeding edge technologies, you're recommended to use one of the following servers.\n\nTheir compliance with the [GraphQL over HTTP spec](https://graphql.github.io/graphql-over-http) is checked automatically and updated regularly.\n\n\u003c!-- \u003cServersTable\u003e --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n| Name | Audit |\n|------|-------|\n| [apollo-server](https://www.apollographql.com/docs/apollo-server) | [✅ Compliant](/implementations/apollo-server/README.md) |\n| [deno](https://deno.com/blog/build-a-graphql-server-with-deno) | [✅ Compliant](/implementations/deno/README.md) |\n| [graph-client](https://github.com/graphprotocol/graph-client) | [✅ Compliant](/implementations/graph-client/README.md) |\n| [graphql-helix](https://www.graphql-helix.com) | [✅ Compliant](/implementations/graphql-helix/README.md) |\n| [graphql-yoga](https://www.the-guild.dev/graphql/yoga-server) | [✅ Compliant](/implementations/graphql-yoga/README.md) |\n| [hotchocolate](https://chillicream.com/docs/hotchocolate) | [✅ Compliant](/implementations/hotchocolate/README.md) |\n| [lighthouse](https://lighthouse-php.com) | [✅ Compliant](/implementations/lighthouse/README.md) |\n| [pioneer](https://pioneer.dexclaimation.com) | [✅ Compliant](/implementations/pioneer/README.md) |\n| [postgraphile](https://www.graphile.org/postgraphile) | [✅ Compliant](/implementations/postgraphile/README.md) |\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- \u003c/ServersTable\u003e --\u003e\n\n## [Documentation](docs/)\n\nCheck the [docs folder](docs/) out for [TypeDoc](https://typedoc.org) generated documentation.\n\n## [Audits](implementations/)\n\nInspect audits of other implementations in the [implementations folder](implementations).\nAdding your implementation is very welcome, [see how](CONTRIBUTING.md#adding-implementations)!\n\n## Want to help?\n\nFile a bug, contribute with code, or improve documentation? [Read more in CONTRIBUTING.md](CONTRIBUTING.md).\n\nIf your company benefits from GraphQL and you would like to provide essential financial support for the systems and people that power our community, please also consider membership in the [GraphQL Foundation](https://foundation.graphql.org/join).\n","funding_links":["https://github.com/sponsors/enisdenjo"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql%2Fgraphql-http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraphql%2Fgraphql-http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql%2Fgraphql-http/lists"}