Is it possible currently to get node.js HTTP/2 (HTTP 2.0) server? And http 2.0 version of express.js?
问题:
回答1:
If you are using express@^5
and http2@^3.3.4
, then the correct way to start the server is:
const http2 = require('http2');
const express = require('express');
const app = express();
// app.use('/', ..);
http2
.raw
.createServer(app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
Notice the https2.raw
. This is required if you want to accept TCP connections.
Note that at the time of this writing (2016 05 06), none of the major browsers support HTTP2 over TCP.
If you want to accept TCP and TLS connections, then you need to start the server using the default createServer
method:
const http2 = require('http2');
const express = require('express');
const fs = require('fs');
const app = express();
// app.use('/', ..);
http2
.createServer({
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
}, app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
Note that at the time of this writing, I did manage to make express
and http2
to work (see https://github.com/molnarg/node-http2/issues/100#issuecomment-217417055). However, I have managed to get http2 (and SPDY) to work using spdy
package.
const spdy = require('spdy');
const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
app.get('/', (req, res) => {
res.json({foo: 'test'});
});
spdy
.createServer({
key: fs.readFileSync(path.resolve(__dirname, './localhost.key')),
cert: fs.readFileSync(path.resolve(__dirname, './localhost.crt'))
}, app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
回答2:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('hello, http2!');
});
var options = {
key: fs.readFileSync('./example/localhost.key'),
cert: fs.readFileSync('./example/localhost.crt')
};
require('http2').createServer(options, app).listen(8080);
EDIT
This code snippet was taken from a conversation on Github.
回答3:
This issue is still around today (over a year later), so I decided to have a go at making a workaround to make express and http2 packages work nicely together. I have created a npm package that does exactly that: https://www.npmjs.com/package/express-http2-workaround
Install via NPM: npm install express-http2-workaround --save
// Require Modules
var fs = require('fs');
var express = require('express');
var http = require('http');
var http2 = require('http2');
// Create Express Application
var app = express();
// Make HTTP2 work with Express (this must be before any other middleware)
require('express-http2-workaround')({ express:express, http2:http2, app:app });
// Setup HTTP/1.x Server
var httpServer = http.Server(app);
httpServer.listen(80,function(){
console.log("Express HTTP/1 server started");
});
// Setup HTTP/2 Server
var httpsOptions = {
'key' : fs.readFileSync(__dirname + '/keys/ssl.key'),
'cert' : fs.readFileSync(__dirname + '/keys/ssl.crt'),
'ca' : fs.readFileSync(__dirname + '/keys/ssl.crt')
};
var http2Server = http2.createServer(httpsOptions,app);
http2Server.listen(443,function(){
console.log("Express HTTP/2 server started");
});
// Serve some content
app.get('/', function(req,res){
res.send('Hello World! Via HTTP '+req.httpVersion);
});
The above code is a working express application that uses both the nodejs http module (for HTTP/1.x) and the http2 module (for HTTP/2).
As mentioned in the readme, this creates new express request and response objects and sets their prototypes to http2's IncomingMessage and ServerResponse objects. By default, it's the inbuilt nodejs http IncomingMessage and ServerResponse objects.
I hope this helps :)