nghttp2をmac osx でビルドしたい

http2confにいるんだが、nghttp2くらいはbuildしてくるべきだった、とかつぶやいたら色々とソリューションを教えてもらった。

自動化させたら世界一の @deeeet さんから[Dockerfile](https://gist.github.com/tcnksm/9b3ef0cf4b58e5ebb723)とかももらったんだけど、Dockerよりももうちょっと手軽にお願いしたかった。nghttp2がmacでビルドできればベスト。



色々試したけど、最終的に夏風さんに頼んでbrewでinstallできるようにしてもらった。

## install nghttp2 by brew

```shell-session
$ curl -o /usr/local/Library/Formula/nghttp2.rb https://gist.githubusercontent.com/summerwind/6295114/raw/nghttp2.rb

$ brew install nghttp2
$ nghttpd --no-tls -v 8888
```

こうしておいて、後は[夏風さんのclientを実装する](https://gist.github.com/summerwind/6295114)。途中までclient頑張って書いてたけど、途中からずるしてコピペした。


## client.js

```js
var net = require('net'),
    hpack = require('./hpack');
 
var FRAME_HEADER_LEN = 9;
 
function createSettingsFrame(ack) {
  var flag = ack ? 0x1 : 0x0;
 
  var frameHeader = new Buffer(FRAME_HEADER_LEN);
  frameHeader.writeUInt32BE(0x0, 0);
  frameHeader.writeUInt8(0x4, 3);
  frameHeader.writeUInt8(flag, 4);
  frameHeader.writeUInt32BE(0x0, 5);
 
  return frameHeader;
}
 
function encodeHeaders(headers) {
  var headerBlocks = [];
 
  headers.forEach(function(header){
    var prefix = new Buffer(1);
    prefix.fill(0);
    headerBlocks.push(prefix);
 
    var name = hpack.encodeString(header[0]);
    headerBlocks.push(name);
 
    var value = hpack.encodeString(header[1]);
    headerBlocks.push(value);
  });
 
  return Buffer.concat(headerBlocks);
}
 
function createHeadersFrame(headers) {
  var headerBlocks = encodeHeaders(headers);
 
  var frameHeader = new Buffer(FRAME_HEADER_LEN);
  frameHeader.writeUInt32BE(headerBlocks.length << 8, 0);
  frameHeader.writeUInt8(0x1, 3);
  frameHeader.writeUInt8(0x5, 4);
  frameHeader.writeUInt32BE(0x1, 5);
 
  return Buffer.concat([frameHeader, headerBlocks]);
};
 
function debug(msg) {
  console.log('[debug]', msg);
}
 
 
var conn = net.connect(8888, '127.0.0.1');
var frameBuffer = new Buffer(0);
var bodyBuffer = [];
 
conn.on('connect', function(){
  conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n', 'utf8');
  conn.write(createSettingsFrame(false));
  debug('Send SETTINGS frame');
});
 
conn.on('data', function(chunk){
  frameBuffer = Buffer.concat([frameBuffer, chunk]);
 
  while (frameBuffer.length >= FRAME_HEADER_LEN) {
    var length = FRAME_HEADER_LEN;
        length += frameBuffer.readUInt32BE(0) >> 8;
    if (frameBuffer.length < length) {
      return;
    }
 
    var frame = frameBuffer.slice(0, length);
    frameBuffer = frameBuffer.slice(length);
 
    if (frame[3] === 0x4 && frame[4] === 0x0) {
      conn.write(createSettingsFrame(true));
      debug('Send SETTINGS frame with ACK flag');
      continue;
    }
 
    if (frame[3] === 0x4 && frame[4] === 0x1) {
      var headers = [
        [ ':method', 'GET' ],
        [ ':path', '/' ],
        [ ':scheme', 'http' ],
        [ ':authority', 'localhost:8888' ]
      ];
 
      conn.write(createHeadersFrame(headers));
      debug('Send HEADERS frame');
      continue;
    }
 
    if (frame[3] === 0x0 && frame[4] === 0x0) {
      bodyBuffer.push(frame.slice(FRAME_HEADER_LEN));
    }
 
    if (frame[3] === 0x0 && frame[4] === 0x1) {
      var body = Buffer.concat(bodyBuffer);
      console.log(body.toString());
      conn.end();
    }
  }
});
```

## hpack.js

```js
function encodeInteger(num, prefix) {
  var limit = Math.pow(2, prefix) - 1;
 
  if (num < limit) {
    return new Buffer([num]);
  }
 
  var octets = [limit];
  num -= limit;
  while (num >= 128) {
    octets.push(num % 128 | 0x80);
    num >>= 7;
  }
  octets.push(num);
 
  return new Buffer(octets);
}
 
function encodeString(str) {
  var buffers = [];
  var value = new Buffer(str, 'ascii');
 
  buffers.push(encodeInteger(value.length, 7));
  buffers.push(value);
 
  return Buffer.concat(buffers);
}
 
exports.encodeInteger = encodeInteger;
exports.encodeString = encodeString;
```

こんな感じで動く。

```shell-session
$ node client.js
<html><head><title>404</title></head><body><h1>404</h1><hr><address>nghttpd nghttp2/0.6.4 at port 8888</address></body></html><html><head><title>404</title></head><body><h1>404</h1><hr><address>nghttpd nghttp2/0.6.4 at port 8888</address></body></html>
```

こんなのが返ってくればOK