Skip to content

Instantly share code, notes, and snippets.

@inian
Last active November 4, 2017 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inian/644aa5cc2dee82782e114a67dde92fb0 to your computer and use it in GitHub Desktop.
Save inian/644aa5cc2dee82782e114a67dde92fb0 to your computer and use it in GitHub Desktop.
Creating a zero-dependency Node.js static file server
const http2 = require('http2');
const fs = require('fs');
const options = {
key: fs.readFileSync('./selfsigned.key'),
cert: fs.readFileSync('./selfsigned.crt'),
allowHTTP1: true
}
const server = http2.createSecureServer(options, (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.end('ok');
});
server.listen(443);
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const {
HTTP2_HEADER_PATH,
HTTP2_HEADER_METHOD,
HTTP_STATUS_NOT_FOUND,
HTTP_STATUS_INTERNAL_SERVER_ERROR
} = http2.constants;
const options = {
key: fs.readFileSync('./selfsigned.key'),
cert: fs.readFileSync('./selfsigned.crt')
}
const server = http2.createSecureServer(options);
const serverRoot = "./public";
function respondToStreamError(err, stream) {
console.log(err);
if (err.code === 'ENOENT') {
stream.respond({ ":status": HTTP_STATUS_NOT_FOUND });
} else {
stream.respond({ ":status": HTTP_STATUS_INTERNAL_SERVER_ERROR });
}
stream.end();
}
server.on('stream', (stream, headers) => {
const reqPath = headers[HTTP2_HEADER_PATH];
const reqMethod = headers[HTTP2_HEADER_METHOD];
const fullPath = path.join(serverRoot, reqPath);
const responseMimeType = mime.lookup(fullPath);
if (fullPath.endsWith(".html")) {
console.log('html');
// handle HTML file
stream.respondWithFile(fullPath, {
"content-type": "text/html"
}, {
onError: (err) => {
respondToStreamError(err, stream);
}
});
stream.pushStream({ ":path": "/font.woff" }, { parent: stream.id }, (pushStream) => {
console.log('pushing');
pushStream.respondWithFile(path.join(serverRoot, "/font.woff"), {
'content-type': "text/css"
}, {
onError: (err) => {
respondToStreamError(err, pushStream);
}
});
});
} else {
// handle static file
console.log(fullPath);
stream.respondWithFile(fullPath, {
'content-type': responseMimeType
}, {
onError: (err) => respondToStreamError(err, stream)
});
}
});
server.listen(443);
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const {
HTTP2_HEADER_PATH,
HTTP2_HEADER_METHOD,
HTTP_STATUS_NOT_FOUND,
HTTP_STATUS_INTERNAL_SERVER_ERROR
} = http2.constants;
const options = {
key: fs.readFileSync('./selfsigned.key'),
cert: fs.readFileSync('./selfsigned.crt')
}
const server = http2.createSecureServer(options);
const serverRoot = "./public";
function respondToStreamError(err, stream) {
console.log(err);
if (err.code === 'ENOENT') {
stream.respond({ ":status": HTTP_STATUS_NOT_FOUND });
} else {
stream.respond({ ":status": HTTP_STATUS_INTERNAL_SERVER_ERROR });
}
stream.end();
}
server.on('stream', (stream, headers) => {
const reqPath = headers[HTTP2_HEADER_PATH];
const reqMethod = headers[HTTP2_HEADER_METHOD];
const fullPath = path.join(serverRoot, reqPath);
const responseMimeType = mime.lookup(fullPath);
stream.respondWithFile(fullPath, {
'content-type': responseMimeType
}, {
onError: (err) => respondToStreamError(err, stream)
});
});
server.listen(443);
@apapirovski
Copy link

For the http2-compatibility-api.js example, one would need allowHTTP1: true as one of the options passed in to the server. Otherwise it just mimics the http API but doesn't actually accept h1 connections. See https://nodejs.org/dist/latest-v8.x/docs/api/http2.html#http2_http2_createsecureserver_options_onrequesthandler

@inian
Copy link
Author

inian commented Nov 4, 2017

@apapirovski - updated!

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