Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

graphql-http

graphql1.8mMIT1.22.4TypeScript support: included

Simple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.

graphql, client, relay, express, apollo, server, http, transport, observables, fastify

readme


graphql-http

Simple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.

Continuous integration graphql-http

Quickly check for compliance? Visit graphql-http.com!

Want a full-featured server? See the servers section!

Need subscriptions? Try graphql-ws or graphql-sse instead!


Getting started

Install

yarn add graphql-http

Create a GraphQL schema

import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';

/**
 * Construct a GraphQL schema and define the necessary resolvers.
 *
 * type Query {
 *   hello: String
 * }
 */
const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      hello: {
        type: GraphQLString,
        resolve: () => 'world',
      },
    },
  }),
});

Start the server

With http
import http from 'http';
import { createHandler } from 'graphql-http/lib/use/http';
import { schema } from './previous-step';

// Create the GraphQL over HTTP Node request handler
const handler = createHandler({ schema });

// Create a HTTP server using the listener on `/graphql`
const server = http.createServer((req, res) => {
  if (req.url.startsWith('/graphql')) {
    handler(req, res);
  } else {
    res.writeHead(404).end();
  }
});

server.listen(4000);
console.log('Listening to port 4000');
With http2

Browsers might complain about self-signed SSL/TLS certificates. Help can be found on StackOverflow.

$ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
  -keyout localhost-privkey.pem -out localhost-cert.pem
import fs from 'fs';
import http2 from 'http2';
import { createHandler } from 'graphql-http/lib/use/http2';
import { schema } from './previous-step';

// Create the GraphQL over HTTP Node request handler
const handler = createHandler({ schema });

// Create a HTTP/2 server using the handler on `/graphql`
const server = http2.createSecureServer(
  {
    key: fs.readFileSync('localhost-privkey.pem'),
    cert: fs.readFileSync('localhost-cert.pem'),
  },
  (req, res) => {
    if (req.url.startsWith('/graphql')) {
      handler(req, res);
    } else {
      res.writeHead(404).end();
    }
  },
);

server.listen(4000);
console.log('Listening to port 4000');
With express
import express from 'express'; // yarn add express
import { createHandler } from 'graphql-http/lib/use/express';
import { schema } from './previous-step';

// Create an express instance serving all methods on `/graphql`
// where the GraphQL over HTTP express request handler is
const app = express();
app.all('/graphql', createHandler({ schema }));

app.listen({ port: 4000 });
console.log('Listening to port 4000');
With fastify
import Fastify from 'fastify'; // yarn add fastify
import { createHandler } from 'graphql-http/lib/use/fastify';
import { schema } from './previous-step';

// Create a fastify instance serving all methods on `/graphql`
// where the GraphQL over HTTP fastify request handler is
const fastify = Fastify();
fastify.all('/graphql', createHandler({ schema }));

fastify.listen({ port: 4000 });
console.log('Listening to port 4000');
With Koa
import Koa from 'koa'; // yarn add koa
import mount from 'koa-mount'; // yarn add koa-mount
import { createHandler } from 'graphql-http/lib/use/koa';
import { schema } from './previous-step';

const app = new Koa();
app.use(mount('/graphql', createHandler({ schema })));

app.listen({ port: 4000 });
console.log('Listening to port 4000');
With uWebSockets.js
import uWS from 'uWebSockets.js'; // yarn add uWebSockets.js@uNetworking/uWebSockets.js#<version>
import { createHandler } from 'graphql-http/lib/use/uWebSockets';
import { schema } from './previous-step';

uWS
  .App()
  .any('/graphql', createHandler({ schema }))
  .listen(4000, () => {
    console.log('Listening to port 4000');
  });
With Deno
import { serve } from 'https://deno.land/std@0.151.0/http/server.ts';
import { createHandler } from 'https://esm.sh/graphql-http/lib/use/fetch';
import { schema } from './previous-step';

// Create the GraphQL over HTTP native fetch handler
const handler = createHandler({ schema });

// Start serving on `/graphql` using the handler
await serve(
  (req: Request) => {
    const [path, _search] = req.url.split('?');
    if (path.endsWith('/graphql')) {
      return handler(req);
    } else {
      return new Response(null, { status: 404 });
    }
  },
  {
    port: 4000, // Listening to port 4000
  },
);
With Bun
import { createHandler } from 'graphql-http/lib/use/fetch'; // bun install graphql-http
import { schema } from './previous-step';

// Create the GraphQL over HTTP native fetch handler
const handler = createHandler({ schema });

// Start serving on `/graphql` using the handler
export default {
  port: 4000, // Listening to port 4000
  fetch(req) {
    const [path, _search] = req.url.split('?');
    if (path.endsWith('/graphql')) {
      return handler(req);
    } else {
      return new Response(null, { status: 404 });
    }
  },
};
With Netlify Functions
import { createHandler } from 'graphql-http/lib/use/@netlify/functions'; // yarn add @netlify/functions
import { schema } from './previous-step';

// Create the GraphQL over HTTP native fetch handler
export const handler = createHandler({ schema });

Use the client

import { createClient } from 'graphql-http';

const client = createClient({
  url: 'http://localhost:4000/graphql',
});

(async () => {
  let cancel = () => {
    /* abort the request if it is in-flight */
  };

  const result = await new Promise((resolve, reject) => {
    let result;
    cancel = client.subscribe(
      {
        query: '{ hello }',
      },
      {
        next: (data) => (result = data),
        error: reject,
        complete: () => resolve(result),
      },
    );
  });

  expect(result).toEqual({ hello: 'world' });
})();

Serve GraphiQL

Thanks to ruru, serving GraphiQL is as easy as running:

npx ruru -SP -p 4001 -e http://localhost:4000/graphql

Open http://localhost:4001 in the browser to use it.

Recipes

<summary>🔗 Client usage with Promise</summary>
import { ExecutionResult } from 'graphql';
import { createClient, RequestParams } from 'graphql-http';
import { getSession } from './my-auth';

const client = createClient({
  url: 'http://hey.there:4000/graphql',
  headers: async () => {
    const session = await getSession();
    if (session) {
      return {
        Authorization: `Bearer ${session.token}`,
      };
    }
  },
});

function execute<Data, Extensions>(
  params: RequestParams,
): [request: Promise<ExecutionResult<Data, Extensions>>, cancel: () => void] {
  let cancel!: () => void;
  const request = new Promise<ExecutionResult<Data, Extensions>>(
    (resolve, reject) => {
      let result: ExecutionResult<Data, Extensions>;
      cancel = client.subscribe<Data, Extensions>(params, {
        next: (data) => (result = data),
        error: reject,
        complete: () => resolve(result),
      });
    },
  );
  return [request, cancel];
}

(async () => {
  const [request, cancel] = execute({
    query: '{ hello }',
  });

  // just an example, not a real function
  onUserLeavePage(() => {
    cancel();
  });

  const result = await request;

  expect(result).toBe({ data: { hello: 'world' } });
})();
<summary>🔗 Client usage with Observable</summary>
import { Observable } from 'relay-runtime';
// or
import { Observable } from '@apollo/client/core';
// or
import { Observable } from 'rxjs';
// or
import Observable from 'zen-observable';
// or any other lib which implements Observables as per the ECMAScript proposal: https://github.com/tc39/proposal-observable
import { createClient } from 'graphql-http';
import { getSession } from './my-auth';

const client = createClient({
  url: 'http://graphql.loves:4000/observables',
  headers: async () => {
    const session = await getSession();
    if (session) {
      return {
        Authorization: `Bearer ${session.token}`,
      };
    }
  },
});

const observable = new Observable((observer) =>
  client.subscribe({ query: '{ hello }' }, observer),
);

const subscription = observable.subscribe({
  next: (result) => {
    expect(result).toBe({ data: { hello: 'world' } });
  },
});

// unsubscribe will cancel the request if it is pending
subscription.unsubscribe();
<summary>🔗 Client usage with Relay</summary>
import { GraphQLError } from 'graphql';
import {
  Network,
  Observable,
  RequestParameters,
  Variables,
} from 'relay-runtime';
import { createClient } from 'graphql-http';
import { getSession } from './my-auth';

const client = createClient({
  url: 'http://i.love:4000/graphql',
  headers: async () => {
    const session = await getSession();
    if (session) {
      return {
        Authorization: `Bearer ${session.token}`,
      };
    }
  },
});

function fetch(operation: RequestParameters, variables: Variables) {
  return Observable.create((sink) => {
    if (!operation.text) {
      return sink.error(new Error('Operation text cannot be empty'));
    }
    return client.subscribe(
      {
        operationName: operation.name,
        query: operation.text,
        variables,
      },
      sink,
    );
  });
}

export const network = Network.create(fetch);
<summary>🔗 Client usage with Apollo</summary>
import {
  ApolloLink,
  Operation,
  FetchResult,
  Observable,
} from '@apollo/client/core';
import { print, GraphQLError } from 'graphql';
import { createClient, ClientOptions, Client } from 'graphql-http';
import { getSession } from './my-auth';

class HTTPLink extends ApolloLink {
  private client: Client;

  constructor(options: ClientOptions) {
    super();
    this.client = createClient(options);
  }

  public request(operation: Operation): Observable<FetchResult> {
    return new Observable((sink) => {
      return this.client.subscribe<FetchResult>(
        { ...operation, query: print(operation.query) },
        {
          next: sink.next.bind(sink),
          complete: sink.complete.bind(sink),
          error: sink.error.bind(sink),
        },
      );
    });
  }
}

const link = new HTTPLink({
  url: 'http://where.is:4000/graphql',
  headers: async () => {
    const session = await getSession();
    if (session) {
      return {
        Authorization: `Bearer ${session.token}`,
      };
    }
  },
});
<summary>🔗 Client usage with request retries</summary>
import { createClient, NetworkError } from 'graphql-http';

const client = createClient({
  url: 'http://unstable.service:4000/graphql',
  shouldRetry: async (err: NetworkError, retries: number) => {
    if (retries > 3) {
      // max 3 retries and then report service down
      return false;
    }

    // try again when service unavailable, could be temporary
    if (err.response?.status === 503) {
      // wait one second (you can alternatively time the promise resolution to your preference)
      await new Promise((resolve) => setTimeout(resolve, 1000));
      return true;
    }

    // otherwise report error immediately
    return false;
  },
});
<summary>🔗 Client usage in browser</summary>
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>GraphQL over HTTP</title>
    <script
      type="text/javascript"
      src="https://unpkg.com/graphql-http/umd/graphql-http.min.js"
    ></script>
  </head>
  <body>
    <script type="text/javascript">
      const client = graphqlHttp.createClient({
        url: 'http://umdfor.the:4000/win/graphql',
      });

      // consider other recipes for usage inspiration
    </script>
  </body>
</html>
<summary>🔗 Client usage in Node</summary>
const fetch = require('node-fetch'); // yarn add node-fetch
const { AbortController } = require('node-abort-controller'); // (node < v15) yarn add node-abort-controller
const { createClient } = require('graphql-http');

const client = createClient({
  url: 'http://no.browser:4000/graphql',
  fetchFn: fetch,
  abortControllerImpl: AbortController, // node < v15
});

// consider other recipes for usage inspiration
<summary>🔗 Client usage in Deno</summary>
import { createClient } from 'https://esm.sh/graphql-http';

const client = createClient({
  url: 'http://deno.earth:4000/graphql',
});

// consider other recipes for usage inspiration
<summary>🔗 Client usage in Bun</summary>
import { createClient } from 'graphql-http'; // bun install graphql-http

const client = createClient({
  url: 'http://bun.bread:4000/graphql',
});

// consider other recipes for usage inspiration
<summary>🔗 Server handler migration from express-graphql</summary>
import express from 'express';
import { schema } from './my-graphql-schema';

-import { graphqlHTTP } from 'express-graphql';
+import { createHandler } from 'graphql-http/lib/use/express';

const app = express();

app.use(
  '/graphql',
-  graphqlHTTP({ schema }),
+  createHandler({ schema }),
);

app.listen(4000);
<summary>🔗 Server handler usage with authentication</summary>

Authenticate 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) because some GraphQL preparations or operations are executed even if the user is not unauthorized.

import { createHandler } from 'graphql-http';
import {
  schema,
  getUserFromCookies,
  getUserFromAuthorizationHeader,
} from './my-graphql';

const handler = createHandler({
  schema,
  context: async (req) => {
    // process token, authenticate user and attach it to your graphql context
    const userId = await getUserFromCookies(req.headers.cookie);
    // or
    const userId = await getUserFromAuthorizationHeader(
      req.headers.authorization,
    );

    // respond with 401 if the user was not authenticated
    if (!userId) {
      return [null, { status: 401, statusText: 'Unauthorized' }];
    }

    // otherwise attach the user to the graphql context
    return { userId };
  },
});
<summary>🔗 Server handler usage with custom context value</summary>
import { createHandler } from 'graphql-http';
import { schema, getDynamicContext } from './my-graphql';

const handler = createHandler({
  schema,
  context: async (req, args) => {
    return getDynamicContext(req, args);
  },
  // or static context by supplying the value directly
});
<summary>🔗 Server handler usage with custom execution arguments</summary>
import { parse } from 'graphql';
import { createHandler } from 'graphql-http';
import { getSchemaForRequest, myValidationRules } from './my-graphql';

const handler = createHandler({
  onSubscribe: async (req, params) => {
    const schema = await getSchemaForRequest(req);

    const args = {
      schema,
      operationName: params.operationName,
      document: parse(params.query),
      variableValues: params.variables,
    };

    return args;
  },
});
<summary>🔗 Server handler usage in Node with early authentication (recommended)</summary>

Authenticate 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.

import { createHandler } from 'graphql-http';
import {
  schema,
  getUserFromCookies,
  getUserFromAuthorizationHeader,
} from './my-graphql';

const handler = createHandler({
  schema,
  context: async (req) => {
    // user is authenticated early (see below), simply attach it to the graphql context
    return { userId: req.raw.userId };
  },
});

const server = http.createServer(async (req, res) => {
  if (!req.url.startsWith('/graphql')) {
    return res.writeHead(404).end();
  }

  try {
    // process token, authenticate user and attach it to the request
    req.userId = await getUserFromCookies(req.headers.cookie);
    // or
    req.userId = await getUserFromAuthorizationHeader(
      req.headers.authorization,
    );

    // respond with 401 if the user was not authenticated
    if (!req.userId) {
      return res.writeHead(401, 'Unauthorized').end();
    }

    const [body, init] = await handler({
      url: req.url,
      method: req.method,
      headers: req.headers,
      body: () =>
        new Promise((resolve) => {
          let body = '';
          req.on('data', (chunk) => (body += chunk));
          req.on('end', () => resolve(body));
        }),
      raw: req,
    });
    res.writeHead(init.status, init.statusText, init.headers).end(body);
  } catch (err) {
    res.writeHead(500).end(err.message);
  }
});

server.listen(4000);
console.log('Listening to port 4000');
<summary>🔗 Server handler usage with graphql-upload and http</summary>
import http from 'http';
import { createHandler } from 'graphql-http/lib/use/http';
import processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload
import { schema } from './my-graphql';

const handler = createHandler({
  schema,
  async parseRequestParams(req) {
    const params = await processRequest(req.raw, req.context.res);
    if (Array.isArray(params)) {
      throw new Error('Batching is not supported');
    }
    return {
      ...params,
      // variables must be an object as per the GraphQL over HTTP spec
      variables: Object(params.variables),
    };
  },
});

const server = http.createServer((req, res) => {
  if (req.url.startsWith('/graphql')) {
    handler(req, res);
  } else {
    res.writeHead(404).end();
  }
});

server.listen(4000);
console.log('Listening to port 4000');
<summary>🔗 Server handler usage with graphql-upload and express</summary>
import express from 'express'; // yarn add express
import { createHandler } from 'graphql-http/lib/use/express';
import processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload
import { schema } from './my-graphql';

const app = express();
app.all(
  '/graphql',
  createHandler({
    schema,
    async parseRequestParams(req) {
      const params = await processRequest(req.raw, req.context.res);
      if (Array.isArray(params)) {
        throw new Error('Batching is not supported');
      }
      return {
        ...params,
        // variables must be an object as per the GraphQL over HTTP spec
        variables: Object(params.variables),
      };
    },
  }),
);

app.listen({ port: 4000 });
console.log('Listening to port 4000');
<summary>🔗 Audit for servers usage in Jest environment</summary>
import { fetch } from '@whatwg-node/fetch';
import { serverAudits } from 'graphql-http';

for (const audit of serverAudits({
  url: 'http://localhost:4000/graphql',
  fetchFn: fetch,
})) {
  test(audit.name, async () => {
    const result = await audit.fn();
    if (result.status === 'error') {
      throw result.reason;
    }
    if (result.status === 'warn') {
      console.warn(result.reason); // or throw if you want full compliance (warnings are not requirements)
    }
    // result.status === 'ok'
  });
}
<summary>🔗 Audit for servers usage in Deno environment</summary>
import { serverAudits } from 'npm:graphql-http';

for (const audit of serverAudits({
  url: 'http://localhost:4000/graphql',
  fetchFn: fetch,
})) {
  Deno.test(audit.name, async () => {
    const result = await audit.fn();
    if (result.status === 'error') {
      throw result.reason;
    }
    if (result.status === 'warn') {
      console.warn(result.reason); // or throw if you want full compliance (warnings are not requirements)
    }
    // Avoid leaking resources
    if ('body' in result && result.body instanceof ReadableStream) {
      await result.body.cancel();
    }
  });
}

Put the above contents in a file and run it with deno test --allow-net.

Only GraphQL over HTTP

This is the official GraphQL over HTTP spec reference implementation and as such follows the specification strictly without any additional features (like playgrounds or GUIs, file uploads, @stream/@defer directives and subscriptions).

Having 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.

Servers

If you want a feature-full server with bleeding edge technologies, you're recommended to use one of the following servers.

Their compliance with the GraphQL over HTTP spec is checked automatically and updated regularly.

Name Audit
apollo-server ✅ Compliant
deno ✅ Compliant
graph-client ✅ Compliant
graphql-helix ✅ Compliant
graphql-yoga ✅ Compliant
hotchocolate ✅ Compliant
lighthouse ✅ Compliant
pioneer ✅ Compliant
postgraphile ✅ Compliant

Documentation

Check the docs folder out for TypeDoc generated documentation.

Audits

Inspect audits of other implementations in the implementations folder. Adding your implementation is very welcome, see how!

Want to help?

File a bug, contribute with code, or improve documentation? Read more in CONTRIBUTING.md.

If 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.

changelog

1.22.4 (2025-01-17)

Bug Fixes

  • use/@netlify/functions: Pass the headers to netlify handler (cd1523f)

1.22.3 (2024-11-20)

Bug Fixes

  • handler: Response options status and statusText are optional (38a0191), closes #133

1.22.2 (2024-11-07)

Bug Fixes

  • use/koa: Use the parsed request body rather than ctx.body (#132) (9f8b1f1)

1.22.1 (2024-04-10)

Bug Fixes

  • audit/render: Omit set-cookie header and html body (#116) (1c5c744)
  • handler: Support both utf-8 and utf8 charsets (94100d6), closes #120
  • use: Set request readable encoding to utf-8 (50d3bcd), closes #118

1.22.0 (2023-08-28)

Features

  • handler: Expose parseRequestParams from the core and each of the adapters (#111) (2caae00)

1.21.0 (2023-07-17)

Bug Fixes

  • client: graphql module is not required for runtime (#102) (9049f31)

Features

1.20.0 (2023-07-08)

Bug Fixes

  • handler: Don't export makeResponse, getAcceptableMediaType or isResponse (#98) (a638cb4)
  • handler: Request params optional properties can also be null (10a6f06)

Features

  • handler: Custom request params parser (#100) (b919d7e)

1.19.0 (2023-06-05)

Bug Fixes

  • use: process global is not available in all environments and NODE_ENV doesn't necessarily depict production vs. development (d08ead3)

Features

1.18.0 (2023-04-14)

Bug Fixes

  • audits/server: Avoid auditing non well-formatted GraphQL-over-HTTP requests (#62) (d72e344)
  • audits/server: Prefer using POST (#77) (8cd7dfb)
  • handler: Stringify errors by exposing only the message (cabf8a9)

Features

  • audits: Notices section for optional recommendations (#76) (b8bdc71)
  • handler: Error formatter function (#78) (c0eaeb4)

1.17.1 (2023-03-31)

Bug Fixes

  • Add file extensions to imports/exports in ESM type definitions (d084a8d), closes #70
  • audits/server: Better "must accept UTF-8" test with emoji (#69) (a322d2c)

1.17.0 (2023-03-28)

Features

  • use/express,use/fastify,use/koa: Request context with the response (665175e), closes #66
  • use/http,use/http2: Request context with the response (e2cc0cd), closes #66

1.16.0 (2023-02-13)

Bug Fixes

  • audits/render: Clone response to allow re-reading the body (#55) (dd4f5f1)

Features

  • use: Deprecate node adapter in favor of http and http2 adapters (f5b0305)
  • use: Each adapter has an adapted HandlerOptions interface (f14a821)

1.15.0 (2023-02-12)

Features

  • audits/render: Render audit results to HTML with renderAuditResultsToHTML (#53) (da32059)
  • Bundle the audits into UMD for browser usage (a402823)
  • Server compliance audit through a website (#54) (f23a689), closes #8

1.14.0 (2023-02-09)

Features

  • handler: Add validationRules option for extending or replacing the GraphQL validation rule set (#51) (46c5309)

1.13.0 (2023-01-26)

Bug Fixes

  • audits/server: JSON parsing errors format shouldnt be audited (#47) (fae7e59)

Features

  • audits: Every audit should have a globally unique ID (#49) (8f6d4f1)

1.12.0 (2023-01-20)

Bug Fixes

  • audits/server: Check the actual content encoding instead of the indication (#41) (67778a8)
  • handler: Response maker handles errors correctly (#45) (5a10e0b)

Features

  • audits/server: Server response in failing audits (#39) (4385ecb)

1.11.0 (2023-01-04)

Features

1.10.0 (2022-12-24)

Features

  • handler: Accept a GraphQL execution rootValue (0f04fa2), closes #30

1.9.0 (2022-11-28)

Bug Fixes

  • audits/server: url option can also just be a Promise (8844aea)

Features

  • audits/server: Test that null is allowed for body parameters (#28) (2dee4ff)

1.8.0 (2022-11-21)

Features

  • audits/server: Support functions for the url option (f4d20a9), closes #24

1.7.2 (2022-11-18)

Bug Fixes

  • handler,audits/server: application/json is the default when accept is missing until watershed (#23) (050fdfe)

1.7.1 (2022-11-15)

Bug Fixes

  • audits/server: A server MAY support GET requests (#18) (9c5e8d2)
  • audits/server: Status code for mutations through GET should be between 400 and 499 (#19) (1021494)

1.7.0 (2022-11-07)

Bug Fixes

  • audits/server: Server may accept other content-type encodings (42c26f7)

Features

  • handler: Headers can be native to fetch (d459991)
  • handler: Supply context to schema option and improve typings (01c45d8)
  • use: Built-in handlers for some environments and frameworks (#13) (750e600)

1.6.1 (2022-09-12)

Bug Fixes

  • server: Accepting application/json SHOULD use status code 200 (9622ea0)
  • server: Adjust audits following the spec (2b21b08)
  • server: Audits requires 4xx shouldnt consider 5xx (59c51fa)
  • server: Audits respect legacy watershed (050c7ba)
  • server: Audits safely handle unparsable JSON in response body (f8098b6)

1.6.0 (2022-09-01)

Features

  • server: Data entry audits when accepting application/graphql-response+json (fe6f60d)

1.5.0 (2022-08-30)

Features

  • server: Audits and test function (#4) (431e513)

1.4.0 (2022-08-16)

Bug Fixes

  • handler: JSON body must be an object (f500fa7)

Features

  • handler: Request's body field may be a parser function (268a4bf)

1.3.0 (2022-08-16)

Features

  • Change GraphQL acceptable media type application/graphql+json to application/graphql-response+json (d86318a)

1.2.0 (2022-08-12)

Bug Fixes

  • handler: onSubscribe can return readonly GraphQLErrors (5ce6841)
  • handler: Allow empty query string parameter (necessary for persisted operations) (4eed1d5)
  • handler: Don't validate if onSubscribe returns execution arguments (17c8007)
  • handler: Respond with error if GraphQL execution result is iterable (d1ffdf7)

Features

  • handler: onSubscribe can return an ExecutionResult for immediate result response (0dcaf89)
  • handler: Expose getAcceptableMediaType and makeResponse for increased modularity (ae8ea29)
  • handler: Request may contain a context value (3a593f8)

Performance Improvements

  • handler: Detect non-string query parameter before parsing (4bc71ee)

1.1.0 (2022-08-05)

Bug Fixes

  • isResponse correctly asserts even if body is null (102de6d)
  • Different types for request and response headers (9e91141)
  • handler: context option can return a response (86c28d1)
  • handler: Match status text with status code (f07454d)
  • handler: More details about parse error (3306cae)

Features

  • client: url option function with request params as argument (99d9086)
  • handler: onSubscribe option can return an array of GraphQL errors (ebd91ad)
  • handler: Custom GraphQL getOperationAST option (f4a2aab)
  • handler: Custom GraphQL parse option (6ef4c57)

1.0.0 (2022-08-04)

Features