0

I have trouble setting up HTTP2 for NodeJS v12.19.0/Express App, provided over an Apache server.

I enabled mod http2 & proxy_http2 and installed npm http2.

The bin/www looks as follows:

var app = require('../app');
var debug = require('debug')('production:server');
var http = require('http2');

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
    return val;
}
if (port >= 0) {
    return port;
}
return false;
}

function onError(error) {
if (error.syscall !== 'listen') {
    throw error;
}

var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;
switch (error.code) {
    case 'EACCES':
    console.error(bind + ' requires elevated privileges');
    process.exit(1);
    break;
    case 'EADDRINUSE':
    console.error(bind + ' is already in use');
    process.exit(1);
    break;
    default:
    throw error;
}
}

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
debug('Listening on ' + bind);
}

The Apache site config:

<VirtualHost *:443>

    Protocols h2 http/1.1

    ServerName domain.com
    ProxyRequests On
    #ProxyPass / http://localhost:3000/
    #ProxyPassReverse / http://localhost:3000/

    ProxyPass / h2://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

Without the lines

ProxyPass / h2://localhost:3000/
ProxyPassReverse / http://localhost:3000/

I get:

Proxy Error

The proxy server received an invalid response from an upstream server. The proxy server could not handle the request

Reason: Error reading from remote server

Apache/2.4.41 (Ubuntu) Server at domain.com Port 443

If I include those lines I get:

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at [no address given] to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log. Apache/2.4.41 (Ubuntu) Server at domain.com Port 443

Help is appreciated..

1 Answers1

0

You are trying to connect from Apache to Node via HTTP/2 over HTTPS (h2) but it doesn't look like from your Node code that you are using TLS certificates so I'd guess it is just an HTTP/2 over HTTP server (h2c).

So replace these lines:

ProxyPass / h2://localhost:3000/
ProxyPassReverse / http://localhost:3000/

With this:

ProxyPass / h2c://localhost:3000/
ProxyPassReverse / http://localhost:3000/

And it should connect over HTTP/2.

However I'd question the value of this. Mod_proxy_http2 is still marked as experimental and the value of backend HTTP/2 connections is very much in question. If you're looking to experiment in Node with HTTP/2 then shouldn't you be connecting directly than via Apache?

Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • Still hits me with 502 and 503 error. I also start to think that express doesn't really support the http2 module. Most examples I found were for spdy, which is deprecated. I connected via Apache since I had it running for my Nextcloud anyway. I have not much deployment experience with node and figured it's kind of like a flask thing were I might benefit from full fledged http server functionality. – nullpointer Oct 15 '20 at 14:52