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

Feature request: auto protocol upgrade from http/1.x to h2 #243

Open
djphoenix opened this issue Jan 21, 2016 · 1 comment
Open

Feature request: auto protocol upgrade from http/1.x to h2 #243

djphoenix opened this issue Jan 21, 2016 · 1 comment

Comments

@djphoenix
Copy link

It seems some browsers may use "upgrade: h2" header to up an connection from plain http to http2 (without tls, so NPN/ALPN unavailable). This is example that works with nghttp -u:

var spdy = require('spdy');
var spdy_transport = require('spdy/node_modules/spdy-transport');
var util = require('util');

function http2_upgrade(req,sock,head) {
  var conn = (req.headers['connection'] || '').toLowerCase().split(/,\s*/);
  var upg = (req.headers['upgrade'] || '').toLowerCase();
  if (
    conn.indexOf('upgrade')!=-1 &&
    conn.indexOf('http2-settings')!=-1 &&
    /^h2c/.test(upg) &&
    'http2-settings' in req.headers
  ) {
    sock.write([
      'HTTP/1.1 101 Switching Protocols',
      'Connection: Upgrade',
      'Upgrade: '+upg,
      '',''
    ].join('\r\n'));
    delete req.headers['upgrade'];
    delete req.headers['connection'];
    delete req.headers['http2-settings'];
    var connection = spdy_transport.connection.create(sock, util._extend({
      protocol: 'http2',
      isServer: true
    }, this._spdyState.options.connection || {}));
    connection.start(4);
    connection.on('error', sock.destroy.bind(sock));
    connection.on('stream', this._onStream.bind(this));
    connection._handleFrame({
      type:'HEADERS',
      id: 1,
      priority: { parent: 0, exclusive: false, weight: 16 },
      fin: false,
      writable: true,
      headers:util._extend(req.headers, {
        ':method': req.method,
        ':path': req.url,
        ':scheme': 'http',
        ':authority': req.headers.host,
      }),
      path: req.url
    });
    return true;
  }
}

module.exports = function(config){
  var spdy_server=spdy.createServer({ spdy: { plain: true, ssl: false } });
  spdy_server.on('upgrade',function(req,sock,head){
    if (http2_upgrade.call(this,req,sock,head)) return;
    if (config.upgrade) return config.upgrade.call(this,req,sock,head);
    sock.end([
      'HTTP/1.1 501 Not Implemented',
      '',''
    ].join('\r\n'));
  });
  if (config.request)
    spdy_server.on('request',config.request);
  if (config.checkContinue)
    spdy_server.on('checkContinue',config.checkContinue);
  spdy_server.listen(80);
  return spdy_server;
}

It's just a "dirty hack". But it works. Why not implement it with right way in right place?

@indutny
Copy link
Collaborator

indutny commented Jan 22, 2016

Perhaps, one day! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants