Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(handler): Expose parseRequestParams from the core and each of the adapters #111

Merged
merged 18 commits into from
Aug 28, 2023

Conversation

enisdenjo
Copy link
Member

@enisdenjo enisdenjo commented Aug 28, 2023

Closes #106
Closes #110

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 });
    }
  },
};

@enisdenjo enisdenjo force-pushed the parse-request-params branch from 08f5d8a to d3fff0d Compare August 28, 2023 11:59
@enisdenjo enisdenjo marked this pull request as ready for review August 28, 2023 14:14
@enisdenjo enisdenjo changed the title feat(handler): Expose parseRequestParams for the core handler and each of the adapters feat(se): Expose parseRequestParams from the core and each of the adapters Aug 28, 2023
@enisdenjo enisdenjo changed the title feat(se): Expose parseRequestParams from the core and each of the adapters feat(handler): Expose parseRequestParams from the core and each of the adapters Aug 28, 2023
@enisdenjo enisdenjo merged commit 2caae00 into main Aug 28, 2023
@enisdenjo enisdenjo deleted the parse-request-params branch August 28, 2023 14:29
enisdenjo pushed a commit that referenced this pull request Aug 28, 2023
# [1.22.0](v1.21.0...v1.22.0) (2023-08-28)

### Features

* **handler:** Expose `parseRequestParams` from the core and each of the adapters ([#111](#111)) ([2caae00](2caae00))
@enisdenjo
Copy link
Member Author

🎉 This PR is included in version 1.22.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@enisdenjo enisdenjo added the released Has been released and published label Aug 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released Has been released and published
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Export parseRequestParams similar to express-graphql
1 participant