I am trying to create a nodejs based http2 server for my application. But at the moment I can't event get to first base and serve index.html when I receive a request for it.
I have a number a module (web.js) which requires what I think I need (some of which is used in the sections of the server that I have replaced with ...
var fs = require('fs');
var path = require('path');
var enableDestroy = require('server-destroy');
var PROJECT_ROOT = path.resolve(__dirname, '..');
var Router = require('router');
var emitter = require('events').EventEmitter;
var util = require('util');
var jwt = require('jwt-simple');
var finalhandler = require('finalhandler');
var semiver = require('semver');
var logger = require('./log');
var router = Router();
var component = Router();
var api = Router();
var serveStatic = require('serve-static');
var bodyParser = require('body-parser');
and then a simple function to create the server and perform the routing. The contents of this function are (abbrieviated)
emitter.call(this);
util.inherits(web,emitter);
this.server = require('http2').createServer(cert);
this.server.on('request',(req,res) => {
var done = finalhandler(req,res);
if(req.url === '/' || req.url === '/index.html') {
if(res.push) { //check for support
logger('debug','creating a push stream');
var favicon = res.push('/favicon.ico');
favicon.writeHead(200);
fs.createReadStream(path.join(PROJECT_ROOT,'app','favicon.ico')).pipe(favicon);
}
}
logger('debug','server request received for ' + req.url );
router(req,res,done);
});
this.server.listen(PORT,hostname);
enableDestroy(this.server); //enhance server with ability to shut it down
router.use('/components/',component);
component.use(serveStatic(path.resolve(PROJECT_ROOT,'app/elements')));
component.use(serveStatic(path.resolve(PROJECT_ROOT,'bower_components')));
router.route('/logon').all(bodyParser.json()).post((req,res) => {
...
});
router.use('/api/',api);
api.use(bodyParser.json());
api.post('/api',(req, res, next) => {
...
});
router.use('/', serveStatic(path.resolve(PROJECT_ROOT,'app')));
logger('debug','server ready for use');
The simple logging function shows the server ready for use, and I can then request either "/" or "/index.html" and it logs that it saw the request and that it was creating the push stream, but from the browser perspective the request is never complete.
I suspect I am not using serveStatic
correctly in the last router.use()
call, but I really can't see any difference to that usage and the use with "component" which is copied from the serverStatic readme.
Can anyone point me in a direction to fix this as I can't seem to take any step forward.
EDIT: I have been doing some debugging of whats happening, as as far as I can see, the serve-static is doing its job just fine, and sending index.html in response the the url '/'. serve-static uses the "send" module to pipe the contents of index.html to the response object.
What seems to happen is that this pipe activity dies before emitting an end event. My suspicion at the moment is that it is the use of the on-finished module which is firing prematurely and closing the stream - but that may be me bad mouthing on-finished because I don't understand it.
http2's equivalent of https.ServerResponse
is OutgoingResponse
.
However it is missing the boolean finished
field. This is used by the on-finished module to determine whether its an incoming or outgoing message and whether it is finished or not. It gets an undefined value and as a result immediately (next clock tick I think) says the stream is finished.
I have patched a finished
field into OutgoingReponse
and it now appears to work.
I have also left an issue on the github repository.
EDIT: This issue has been recognised and is now incorporated in the latest release.