Koa: HTTP/2 support

Created on 7 Sep 2015  路  28Comments  路  Source: koajs/koa

Hi,

Is there any plan to support HTTP/2 in Koa?

Thanks!

Most helpful comment

Node.js v8.4.0 starts supporting http2.
@jonathanong please reopen this issue and put http2 on the agenda. :nerd_face:

All 28 comments

you can use https://github.com/indutny/node-spdy, which AFAIK supports HTTP 2

koa is server agnostic - just create wrap the app in whichever server implementation you'd like.

if you were looking for a http push helper, you can try https://github.com/jshttp/spdy-push

Hi @jonathanong, thanks for clarifying that Koa is server agnostic, I will look into the server implementation that best suits my use case!

Apart from this, in Koala's docs there's a section that states:

Once SPDY becomes an HTTP standard and is baked into node.js, some of these features will be placed in Koa.

In my understanding, HTTP/2 has replaced and extended the SPDY protocol (which will not be supported from Google from early 2016 onwards).

As for the differences between SPDY adn HTTP/2, some information can be found in the Wiki link that I posted in the first comment: https://en.wikipedia.org/wiki/HTTP/2

Putting the two pieces of information together, I wondered if there was any plan to integrate HTTP/2 as the standard app.listen() in future Koa versions.

Cheers!

app.listen() will continue use require('http') by default. we just gotta wait until node supports http2 out of the box.

I'm curious if anyone actually got this to work. I was trying to use node-http2 and this very simple example:

var http = require('http2');
var koa = require('koa');
var app = koa();

var options = {
  key: fs.readFileSync('./localhost.key'),
  cert: fs.readFileSync('./localhost.crt')
};

var handleRequest = function*(next) {
  this.body = 'Hello World';
  yield next;
  console.log('done');
};

app.use(handleRequest);
http.createServer(options, app.callback()).listen(8080);

never completes the request. From the client perspective, the request is 'pending' forever, and there are no errors in node. The line console.log('done'); is hit and writes to the console.

If I swap the require from 'http2' to 'http' then it works fine.


_Update 1:_

I found that Koa response.js contains:

  get writable() {
    var socket = this.res.socket;
    if (!socket) return false;
    return socket.writable;
  },

In that function, this.res is the "raw" response object from http2, but it turns out that http2 module doesn't have a .socket property as the "normal" http module would.

writable then returns false which prevents ctx.res.end() from ever being called, so the server holds the request open forever.

This might make koa and http2 (that specific implementation anyway) incompatible.

response.socket seems to be an undocumented part of the Node HTTP spec (see: ServerResponse ) so if Koa's goal is to be server agnostic, it would be good to find a way to not use undocumented/internal implementation details of Node's default http module.

Confirmed what @rally25rs mentioned about node-http2 module. I had the same issue today with [email protected]. Also traced down to response.writable. Good catch!


Update:

I forked node-http2 module and added socket to response object. Hope that helps.

git+https://github.com/tomchentw/node-http2.git#fix/koa-compatibility

As of release 3.3.2 (maybe earlier) of node-http2, the response object has a .socket property as suggested by @tomchentw above.

I was just about to raise up an issue on node-http2. Thanks @pieterb for the comment. But at the moment I forked from node-http2, it's 3.3.2 and there's no response.socket exists.

I also checked their latest code but with no luck. Would you mind to point out where it is?


Update: I've switched implementation from node-http2 to node-spdy. If anyone is interested my fork of node-http2, here's the diff:

lib/http.js

@@ -504,6 +504,10 @@ Server.prototype._start = function _start(socket) {
     request.remoteAddress = socket.remoteAddress;
     request.remotePort = socket.remotePort;
     request.connection = request.socket = socket;
+    //
+    // https://github.com/koajs/koa/issues/477#issuecomment-170950919
+    //
+    response.socket = socket;

     request.once('ready', self.emit.bind(self, 'request', request, response));
   });

Adding it to node-http2 seems like fixing the wrong thing to me; response.socket is an implementation detail of node's http implementation that is not a documented part of the API, so other libraries (namely koa) shouldn't rely on its existence.

Hi @tomchentw, there was a link in my earlier comment, but here's a link to the specific version, file and line:
https://github.com/molnarg/node-http2/blob/v3.3.2/lib/http.js#L506

UPDATE:
request.socket was introduced in this commit, on August 28 2015.

Oops, I'm mistaken: that commit introduced request.socket. You're talking about response.socket. No, this hasn't been introduced into node-http2. Please send the pull-request!

@pieterb what do you think about the comment from @rally25rs ? I'm concerning about it too and I'm seeing my fork of node-http2 is just a hacky solution.

@tomchentw I'd say @rally25rs' comment makes a lot of sense. I've been trying to understand the relevant bits of code in koajs and node's core http and https modules, but I don't feel confident enough to create a pull request.

To be honest, I don't (fully) understand the reasoning behind testing the socket's writability in the first place. AFAICS, the intention is to check if the user has bypassed koa's response object and called res.write() or res.end() on the underlying lower-level reponse object. The test was introduced in commit 9fe483ca767b64de3e9b9e2c78b7bfaf420861c2, without explanation.

I've been looking into this a bit further. There's some interesting discussion on this topic in issues #142 and #143. I suggest we continue this discussion under #143, and convince the koa team to undo that commit (9fe483ca767b64de3e9b9e2c78b7bfaf420861c2).

Please make a nice way to use http2 with koa without having to resort to writing a full infrastructure around spdy or similar :)

@kristianmandrup I'm playing around with node-spdy and koa@2 and have gotten a fair bit.

There's a brief explanation along with some code examples over at node-spdy#277

Semi working as of now, at this point I can push resources out to the client w/ manifest support.

It doesn't work quite as well when bumping up the amount of resources to push (from ~5 to ~100) as it seems to always end up in a ton of FLOW_CONTROL_ERROR's so I'm definitely doing _something_ wrong.

I'll see about extracting the necessary bits of code into a repo where it's easily hackable.


I know that's not what you were asking for here, but it's a starting point(?) I reckon.

@kristianmandrup I've pushed what I have so far into this repo https://github.com/kasperlewau/koa-h2-man-pusher.

It's still very much a work in progress. There's a couple of examples in the /examples dir that can be run with node server.js. That will bootup a SPDY server w/ self signed certs on port 3000. The examples cover three cases; 16, 100 & 200 assets pushed to the client.

Again, it's not quite what you're asking for as far as spdy support within koa goes - but I suppose it's a start 馃槃

@kasperlewau Sweet :) Good job!

is it worth reopening this issue now that node is about to support http2 from the core?
https://medium.com/the-node-js-collection/say-hello-to-http-2-for-node-js-core-261ba493846e
https://github.com/nodejs/node/pull/14239

A api to things like server push is a cool feature

FWIW, it looks like http2 landed in node core a few days ago so people can start experimenting with it.

Please reopen.

Node.js v8.4.0 starts supporting http2.
@jonathanong please reopen this issue and put http2 on the agenda. :nerd_face:

Reopen? @jonathanong

Is this literally as easy as swapping out http for http2? If so I'll fork/maintain until they catch up.

Is there any benefit to using http2 other than push?

http2 supports better parallel fetching of assets and a whole host of other optimisations besides push...

are push streams supported?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ke1Del picture ke1Del  路  3Comments

rainesinternationaldev picture rainesinternationaldev  路  5Comments

wlingke picture wlingke  路  3Comments

rowild picture rowild  路  4Comments

tvq picture tvq  路  4Comments