Skip to content

Releases: graphql/graphql-http

v1.22.1

10 Apr 18:03
Compare
Choose a tag to compare

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

v1.22.0

28 Aug 14:50
Compare
Choose a tag to compare

1.22.0 (2023-08-28)

Features

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

Examples

Request params parser usage with http

import http from 'http';
import { parseRequestParams } from 'graphql-http/lib/use/http';

const server = http.createServer(async (req, res) => {
  if (req.url.startsWith('/graphql')) {
    try {
      const maybeParams = await parseRequestParams(req, res);
      if (!maybeParams) {
        // not a well-formatted GraphQL over HTTP request,
        // parser responded and there's nothing else to do
        return;
      }

      // well-formatted GraphQL over HTTP request,
      // with valid parameters
      res.writeHead(200).end(JSON.stringify(maybeParams, null, '  '));
    } catch (err) {
      // well-formatted GraphQL over HTTP request,
      // but with invalid parameters
      res.writeHead(400).end(err.message);
    }
  } else {
    res.writeHead(404).end();
  }
});

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

Request params parser usage with http2

$ 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 { parseRequestParams } from 'graphql-http/lib/use/http2';

const server = http2.createSecureServer(
  {
    key: fs.readFileSync('localhost-privkey.pem'),
    cert: fs.readFileSync('localhost-cert.pem'),
  },
  async (req, res) => {
    if (req.url.startsWith('/graphql')) {
      try {
        const maybeParams = await parseRequestParams(req, res);
        if (!maybeParams) {
          // not a well-formatted GraphQL over HTTP request,
          // parser responded and there's nothing else to do
          return;
        }

        // well-formatted GraphQL over HTTP request,
        // with valid parameters
        res.writeHead(200).end(JSON.stringify(maybeParams, null, '  '));
      } catch (err) {
        // well-formatted GraphQL over HTTP request,
        // but with invalid parameters
        res.writeHead(400).end(err.message);
      }
    } else {
      res.writeHead(404).end();
    }
  },
);

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

Request params parser usage with express

import express from 'express'; // yarn add express
import { parseRequestParams } from 'graphql-http/lib/use/express';

const app = express();
app.all('/graphql', async (req, res) => {
  try {
    const maybeParams = await parseRequestParams(req, res);
    if (!maybeParams) {
      // not a well-formatted GraphQL over HTTP request,
      // parser responded and there's nothing else to do
      return;
    }

    // well-formatted GraphQL over HTTP request,
    // with valid parameters
    res.writeHead(200).end(JSON.stringify(maybeParams, null, '  '));
  } catch (err) {
    // well-formatted GraphQL over HTTP request,
    // but with invalid parameters
    res.writeHead(400).end(err.message);
  }
});

app.listen({ port: 4000 });
console.log('Listening to port 4000');

Request params parser usage with fastify

import Fastify from 'fastify'; // yarn add fastify
import { parseRequestParams } from 'graphql-http/lib/use/fastify';

const fastify = Fastify();
fastify.all('/graphql', async (req, reply) => {
  try {
    const maybeParams = await parseRequestParams(req, reply);
    if (!maybeParams) {
      // not a well-formatted GraphQL over HTTP request,
      // parser responded and there's nothing else to do
      return;
    }

    // well-formatted GraphQL over HTTP request,
    // with valid parameters
    reply.status(200).send(JSON.stringify(maybeParams, null, '  '));
  } catch (err) {
    // well-formatted GraphQL over HTTP request,
    // but with invalid parameters
    reply.status(400).send(err.message);
  }
});

fastify.listen({ port: 4000 });
console.log('Listening to port 4000');

Request params parser usage with Koa

import Koa from 'koa'; // yarn add koa
import mount from 'koa-mount'; // yarn add koa-mount
import { parseRequestParams } from 'graphql-http/lib/use/koa';

const app = new Koa();
app.use(
  mount('/', async (ctx) => {
    try {
      const maybeParams = await parseRequestParams(ctx);
      if (!maybeParams) {
        // not a well-formatted GraphQL over HTTP request,
        // parser responded and there's nothing else to do
        return;
      }

      // well-formatted GraphQL over HTTP request,
      // with valid parameters
      ctx.response.status = 200;
      ctx.body = JSON.stringify(maybeParams, null, '  ');
    } catch (err) {
      // well-formatted GraphQL over HTTP request,
      // but with invalid parameters
      ctx.response.status = 400;
      ctx.body = err.message;
    }
  }),
);

app.listen({ port: 4000 });
console.log('Listening to port 4000');

Request params parser usage with uWebSockets.js

import uWS from 'uWebSockets.js'; // yarn add uWebSockets.js@uNetworking/uWebSockets.js#<version>
import { parseRequestParams } from 'graphql-http/lib/use/uWebSockets';

uWS
  .App()
  .any('/graphql', async (res, req) => {
    const abortedRef = { current: false };
    res.onAborted(() => (abortedRef.current = true));
    try {
      const maybeParams = await parseRequestParams(req, res, abortedRef);
      if (!maybeParams) {
        // not a well-formatted GraphQL over HTTP request,
        // parser responded and there's nothing else to do
        return;
      }

      // well-formatted GraphQL over HTTP request,
      // with valid parameters
      if (!abortedRef.current) {
        res.writeStatus('200 OK');
        res.end(JSON.stringify(maybeParams, null, '  '));
      }
    } catch (err) {
      // well-formatted GraphQL over HTTP request,
      // but with invalid parameters
      if (!abortedRef.current) {
        res.writeStatus('400 Bad Request');
        res.end(err.message);
      }
    }
  })
  .listen(4000, () => {
    console.log('Listening to port 4000');
  });

Request params parser usage with Deno

import { serve } from 'https://deno.land/std@0.151.0/http/server.ts';
import { parseRequestParams } from 'https://esm.sh/graphql-http/lib/use/fetch';

await serve(
  async (req: Request) => {
    const [path, _search] = req.url.split('?');
    if (path.endsWith('/graphql')) {
      try {
        const paramsOrResponse = await parseRequestParams(req);
        if (paramsOrResponse instanceof Response) {
          // not a well-formatted GraphQL over HTTP request,
          // parser created a response object to use
          return paramsOrResponse;
        }

        // well-formatted GraphQL over HTTP request,
        // with valid parameters
        return new Response(JSON.stringify(paramsOrResponse, null, '  '), {
          status: 200,
        });
      } catch (err) {
        // well-formatted GraphQL over HTTP request,
        // but with invalid parameters
        return new Response(err.message, { status: 400 });
      }
    } else {
      return new Response(null, { status: 404 });
    }
  },
  {
    port: 4000, // Listening to port 4000
  },
);

Request params parser usage with Bun

import { parseRequestParams } from 'graphql-http/lib/use/fetch'; // bun install graphql-http

export default {
  port: 4000, // Listening to port 4000
  async fetch(req) {
    const [path, _search] = req.url.split('?');
    if (path.endsWith('/graphql')) {
      try {
        const paramsOrResponse = await parseRequestParams(req);
        if (paramsOrResponse instanceof Response) {
          // not a well-formatted GraphQL over HTTP request,
          // parser created a response object to use
          return paramsOrResponse;
        }

        // well-formatted GraphQL over HTTP request,
        // with valid parameters
        return new Response(JSON.stringify(paramsOrResponse, null, '  '), {
          status: 200,
        });
      } catch (err) {
        // well-formatted GraphQL over HTTP request,
        // but with invalid parameters
        return new Response(err.message, { status: 400 });
      }
    } else {
      return new Response(null, { status: 404 });
    }
  },
};

v1.21.0

17 Jul 10:10
Compare
Choose a tag to compare

1.21.0 (2023-07-17)

Bug Fixes

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

Features

Examples

Start the server 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 });

v1.20.0

08 Jul 09:55
Compare
Choose a tag to compare

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)

Examples

Server handler usage with graphql-upload and http

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');

Server handler usage with graphql-upload and express

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');

v1.19.0

05 Jun 13:54
Compare
Choose a tag to compare

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

Examples

Start the server 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 './my-graphql-schema';

uWS
  .App()
  .any('/graphql', createHandler({ schema }))
  .listen(4000, () => {
    console.log('Listening to port 4000');
  });

v1.18.0

14 Apr 00:30
Compare
Choose a tag to compare

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)

v1.17.1

31 Mar 11:40
Compare
Choose a tag to compare

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)

v1.17.0

28 Mar 15:13
Compare
Choose a tag to compare

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

v1.16.0

13 Feb 14:26
Compare
Choose a tag to compare

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)

v1.15.0

12 Feb 22:06
Compare
Choose a tag to compare

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, visit graphql-http.com