GraphQL over HTTP Protocol Implementation
graphql-http is a robust, zero-dependency JavaScript library that provides a spec-compliant implementation of GraphQL over HTTP for both server and client applications. It is currently at version 1.22.4 and receives regular updates, primarily focusing on bug fixes, performance improvements, and new platform integrations, as evidenced by its recent release cadence. The library distinguishes itself through its strict adherence to the official GraphQL over HTTP specification, offering a pluggable architecture that integrates seamlessly with various Node.js HTTP frameworks like `http`, `http2`, `Express`, `Fastify`, `Koa`, and serverless environments. It also includes an audit suite to verify compliance, making it a reliable choice for building standard-compliant GraphQL endpoints without the overhead of larger frameworks like Apollo Server, or for creating custom GraphQL clients.
Common errors
-
ERR_REQUIRE_ESM: require() of ES Module ... not supported
cause Attempting to use `require()` to import `graphql-http` or its adapter modules in a CommonJS context, while `graphql-http` is primarily an ESM package.fixEnsure your project is configured for ESM (add `"type": "module"` to `package.json` or use `.mjs` file extensions for source files) and use `import` statements: `import { createHandler } from 'graphql-http/lib/use/express';`. -
TypeError: Cannot read properties of undefined (reading 'query')
cause The HTTP framework (e.g., Express, Koa, Fastify) is not parsing the request body before `graphql-http` attempts to access it, typically occurring with POST requests carrying GraphQL queries in the body.fixAdd appropriate body parsing middleware *before* the `graphql-http` handler. For Express: `app.use(express.json());`. For Koa (as indicated by a v1.22.2 fix), ensure `koa-body` or similar is used correctly and the handler receives the parsed body via `ctx.request.body`. -
Error: Must provide document. | GraphQL schema is not valid.
cause The `schema` object provided to `createHandler` is either `undefined`, `null`, or not a valid `GraphQLSchema` instance from the `graphql` library, indicating an issue with schema definition or import.fixVerify that the `graphql` peer dependency is installed and that the `schema` object passed to `createHandler` is a correctly instantiated `GraphQLSchema` from the `graphql` package. Double-check your `graphql` package version for compatibility with `graphql-http`.
Warnings
- breaking Internal utilities `makeResponse`, `getAcceptableMediaType`, and `isResponse` were explicitly removed from public export in v1.20.0. Code directly importing these internal helpers will break.
- gotcha As of v1.17.1, file extensions were added to imports/exports in ESM type definitions to improve compatibility with Node.js ESM resolution and bundlers. Older TypeScript configurations or bundlers might encounter 'module not found' errors if they do not correctly resolve `.js` extensions for ESM imports.
- gotcha `graphql-http` has a peer dependency on the `graphql` library (typically `graphql@^15.0.0` or `graphql@^16.0.0`, but check `peerDependencies` in `package.json`). Using an incompatible version of `graphql` can lead to runtime errors or unexpected behavior due to API mismatches.
- gotcha When using `graphql-http` with frameworks like Express or Fastify, you must ensure that the request body is correctly parsed *before* the `graphql-http` handler processes it. `graphql-http` expects the raw request body data to be available, typically as JSON for POST requests.
Install
-
npm install graphql-http -
yarn add graphql-http -
pnpm add graphql-http
Imports
- createHandler
const { createHandler } = require('graphql-http/lib/use/express');import { createHandler } from 'graphql-http/lib/use/express'; - createHandler
import { createHandler } from 'graphql-http/lib/use/http';import { createHandler } from 'graphql-http'; - createClient
import { createClient } from 'graphql-http/lib/client';import { createClient } from 'graphql-http'; - parseRequestParams
import { parseRequestParams } from 'graphql-http';import { parseRequestParams } from 'graphql-http/lib/parse';
Quickstart
import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';
import express from 'express';
import { createHandler } from 'graphql-http/lib/use/express';
// Define a simple GraphQL schema for demonstration
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: () => 'world',
},
echo: {
type: GraphQLString,
args: { message: { type: GraphQLString } },
resolve: (source, { message }) => `You said: ${message}`,
},
},
}),
});
const app = express();
// Middleware to parse JSON bodies for GraphQL POST requests
app.use(express.json());
// Create an Express-specific GraphQL over HTTP handler
app.all('/graphql', createHandler({
schema,
// Optional: Add a context factory to pass request-specific data to resolvers
context: (req) => ({
userId: req.headers['x-user-id'] ?? 'guest',
// Any other request-scoped data
}),
}));
const port = process.env.PORT ? parseInt(process.env.PORT) : 4000;
app.listen(port, () => {
console.log(`GraphQL server running at http://localhost:${port}/graphql`);
console.log(`
To test, run in another terminal:
curl -X POST -H "Content-Type: application/json" \
--data '{"query":"query { hello }"}' \
http://localhost:${port}/graphql
`);
console.log(` curl -X POST -H "Content-Type: application/json" \
--data '{"query":"query { echo(message: \"Hello GraphQL\") }"}' \
http://localhost:${port}/graphql
`);
});