apollo-server icon indicating copy to clipboard operation
apollo-server copied to clipboard

Error when using HTTP2

Open abrenneke opened this issue 7 years ago • 8 comments

apollo-server doesn't seem to like when Node's http2 module is used. When an HTTP2 client (i.e. the browser) makes a request, this error happens:

TypeError: :method is not a legal HTTP header name

  - index.js:670 validateName
    [venom-api]/[apollo-server-env]/[node-fetch]/lib/index.js:670:9

  - index.js:830 Headers.append
    [venom-api]/[apollo-server-env]/[node-fetch]/lib/index.js:830:3

  - nodeHttpToRequest.ts:11 Object.keys.forEach.key
    [venom-api]/[apollo-server-core]/src/nodeHttpToRequest.ts:11:15

  - Array.forEach

  - nodeHttpToRequest.ts:6 Object.convertNodeHttpToRequest
    [venom-api]/[apollo-server-core]/src/nodeHttpToRequest.ts:6:28

...more stuff

Since apollo-server-core uses Request and Headers objects from node-fetch, I'm not sure whether this is an upstream problem or not. The problem is that node-fetch doesn't seem to support the "special" header names documented here.

In HTTP/2, the request path, hostname, protocol, and method are represented as special headers prefixed with the : character (e.g. ':path'). These special headers will be included in the request.headers object.

Since nodeHttpToRequest isn't actually using node-fetch to make an HTTP request, this seems to me like a problem internal to Apollo Server. node-fetch has their own issue here for HTTP2, but that seems to be concerned with making HTTP2 requests.

Reproduction:

(I use Koa)

const Koa = require('koa');
const { ApolloServer } = require('apollo-server-koa');
const http2 = require('http2');

const app = new Koa();
const apollo = new ApolloServer({ etc });
apollo.applyMiddleware(app);
const server = http2.createSecureServer({ cert: 'cert here', key: 'key here' }, app.callback());
server.listen(8000);

Then make a GraphQL request, with your browser, to https://localhost:8000/ (browsers do not allow insecure HTTP2, so you'll have to ignore the security warning)

Potential Fix

In nodeHttpToRequest, ignore headers starting with :

abrenneke avatar Aug 15 '18 05:08 abrenneke

Also interested in having HTTP2 work with Apollo. Since Express doesn't support HTTP2 natively yet, it may be worth creating a wrapper for spdy with an HTTP2 boolean flag that can be passed in when calling / creating a new ApolloServer

selipso avatar Oct 17 '18 18:10 selipso

I'm interested in using HTTP2 in fastify.

mzygmunt avatar May 09 '19 14:05 mzygmunt

I'm interested in using it in koa

Dbuggerx avatar Oct 16 '19 08:10 Dbuggerx

Please extend the HTTP 2 support for Restdatasource also

sensha4u avatar Apr 04 '20 14:04 sensha4u

any updates on this?

devdudeio avatar Dec 02 '20 03:12 devdudeio

Has any progress been made on this front, or any additional plans formed?

theJC avatar Jan 28 '21 20:01 theJC

Problem is in node-fetch library, where is test for header token name.

original `node_modules/apollo-server-env/node_modules/node-fetch/lib/index.js

...
const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
...

when change to

...
const invalidTokenRegex = /[^\^_`:a-zA-Z\-0-9!#$%&'*+.|~]/;
...

It start working.

andreas4all avatar Jan 25 '22 16:01 andreas4all

While I know this isn't the most exciting thing to hear, I think this will get naturally fixed as part of Apollo Server 4 which we expect to ship in the first half of this year. It looks like the problem is that we normalize incoming requests to the Request type from node-fetch, which doesn't allow for the special HTTP/2 headers. We'll be defining our own request type in AS4 (see eg the HTTPGraphQLRequest proposal in #3184) and we'll avoid using node-fetch's Request for that, which should solve the issue.

glasser avatar Jan 25 '22 23:01 glasser

Apollo 4 is still in Alpha. Also it's been four years. The only thing missing is literally a colon. Will you accept a merge-request where I replace node-fetch with a fixed version?

annitya avatar Sep 27 '22 16:09 annitya

Apollo Server 4 is going into release candidate today. As mentioned above, this changes the type used to represent requests from node-fetch's (which doesn't allow for special HTTP/2 headers) to our own simpler type.

I'm going to close this issue as fixed on the version-4 branch; it would be great if HTTP/2 users could verify this.

glasser avatar Sep 27 '22 18:09 glasser

Provide an example to how to create apollo server with http2 and express.

kiran052 avatar Jan 03 '23 10:01 kiran052