Search code examples
node.jssslhttpshttp2

NodeJS HTTP/2 ERR_CONNECTION_REFUSED


I am attempting to implement HTTP/2 on a node server using molnarg's node-http2 module. My original server.js works fine and when I implemented the HTTP/2 module I get a

ERR_CONNECTION_REFUSED

from the browser (using Chrome on a ChromeBook).

List of changes to implement HTTP/2:

  1. Created the cert & key .perm's
  2. Changed the hostPort var in the config.json to 443 (tried w/80, 8000)
  3. Add to server.js:

    var certs = {key: fs.readFileSync('../../key.pem'),cert: fs.readFileSync('../../cert.pem')};

  4. Edit server.js

    require('http').createServer(function (request, response) {...}

    to

    require('http2').createServer(certs, function (request, response) {...}

What am I missing or have wrong (I get no errors in the log)?

Below is a copy of the server.js

var environment = '../env/' + process.env.NODE_ENV;

// Process User config
var fS = require('fs')
  , jsonFile = fS.readFileSync(environment + '/config.json'), jsonString, hostIp, hostPort, cacheExp, cps;

try {
  jsonString              = JSON.parse(jsonFile);
  var SERV_HOST           = jsonString['hostIp']
    , SERV_PORT           = jsonString['hostPort']
    , CACHE_EXP           = jsonString['cacheExp']
    , CPS                 = jsonString['cps']
    , xPowerBy            = ''
    , xFrameOptions       = ''
    , xXSSProtection      = ''
    , xContentTypeOption  = ''
    , cacheControl        = '';
} catch (err) {
  console.log('There is an error parsing the json file : ' + err);
}

// Load required modules
var web       = require('node-static')
  , watch     = require('staticsmith-watch')
  , fs        = require("fs");

var certs = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
};

// Load security setings via config.json
var security  =
    [{
      // Just some security stuff here
    }];

if (process.env.NODE_ENV == 'production') {

  var options = { host:   SERV_HOST
                , port:   SERV_PORT
                , cache:  CACHE_EXP
  };

  var public_dir = new web.Server(environment, options);

  // Serve it up!
  require('http2').createServer(certs, function (request, response) {
  // OLD 
  // require('http').createServer(function (request, response) {

    // Add Content Security Rules
    for(var i = 0; i < security.length; i++){
        response.setHeader(security[i].name, security[i].option);
      }

    request.addListener('end', function () {

        public_dir.serve(request, response, function (err, result) {
            if (err) { // There was an error serving the file
                console.error("Error serving " + request.url + " - " + err.message);
                // Respond to the client
                response.writeHead(err.status, err.headers);
                response.end();
            }
        });
    }).resume();
  }).listen(options.port, options.host);

  console.log("serving at http://" + options.host + ":" + options.port);
  console.log("On Node v" + process.versions.node);

  watch({
    pattern:    '**/*',
    livereload: true,
  });
}

Solution

  • Implementation of node-spdy was used in lieu of node-http2 because this module you can create HTTP2 / SPDY servers in node.js with natural http module interface and fallbacks to regular https (for browsers that don't support neither HTTP2, nor SPDY yet).

    The above server.js now implementing the new module:

    var environment = '../env/' + process.env.NODE_ENV;
    
    // Process User config
    var fS = require('fs')
      , jsonFile = fS.readFileSync(environment + '/config.json'), jsonString, hostIp, hostPort, cacheExp, cps;
    
    try {
      jsonString              = JSON.parse(jsonFile);
      var SERV_HOST           = jsonString['hostIp']
        , SERV_PORT           = jsonString['hostPort']
        , CACHE_EXP           = jsonString['cacheExp']
        , CPS                 = jsonString['cps']
        , xPowerBy            = ':P'
        , xFrameOptions       = ''
        , xXSSProtection      = ''
        , xContentTypeOption  = ''
        , cacheControl        = '';
    } catch (err) {
      console.log('There is an error parsing the json file : ' + err);
    }
    
    // Load required modules
    var fs    = require('fs')
      , web   = require('node-static');
    
    var public_dir = new web.Server(environment + '/_public');
    
    var options = {
        key: fs.readFileSync(environment + '/keys/key.pem')
      , cert: fs.readFileSync(environment + '/keys/cert.pem')
    
      // SPDY-specific options 
      , spdy: {
          protocols: [ 'h2','spdy/3.1', 'spdy/3', 'spdy/2','http/1.1', 'http/1.0' ],
          plain: false,
    
          connection: {
            windowSize: 1024 * 1024, // Server's window size 
    
            // **optional** if true - server will send 3.1 frames on 3.0 *plain* spdy 
            autoSpdy31: false
          }
        }
    
      , host:   SERV_HOST
      , port:   SERV_PORT
      , cache:  CACHE_EXP
    
    };
    
    // Load security setings via config.json
    var security  = [
        { name:   'X-Powered-By',
          option: xPowerBy }
      , { name:   'x-frame-options',
          option: xFrameOptions }
      , { name:   'X-XSS-Protection',
          option: xXSSProtection }
      , { name:   'X-Content-Type-Options',
          option: xContentTypeOption }
      , { name:   'Cache-Control',
          option: CACHE_EXP }
      , { name:   'Content-Security-Policy',
          option: CPS }
      , { name:   'server',
          option: 'Who knows' }
    ];
    
    if (process.env.NODE_ENV == 'production') {
    
      require("spdy").createServer(options, function(req, res) {
    
        // Add Content Security Rules
        for(var i = 0; i < security.length; i++){
          res.setHeader(security[i].name, security[i].option);
        }
    
        public_dir.serve(req, res, function (err, result) {
          if (err) { // There was an error serving the file
            console.error("Error serving " + req.url + " - " + err.message);
            // Respond to the client
            res.writeHead(err.status, err.headers);
            res.end();
          }
        });
      }).listen(options.port, options.host);
      console.log("serving at https://" + options.host + ":" + options.port);
      console.log("On Node v" + process.versions.node);
    }
    

    This worked out of the box.