Skip to content

Instantly share code, notes, and snippets.

@mfellner
Created July 18, 2019 07:07
Show Gist options
  • Save mfellner/da92b6bd78d8536755b29892b85479da to your computer and use it in GitHub Desktop.
Save mfellner/da92b6bd78d8536755b29892b85479da to your computer and use it in GitHub Desktop.
Node.js static file server.
/* eslint-env node */
const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
const { exec } = require('child_process');
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
const hostname = '127.0.0.1';
const port = 3030;
const staticDir = path.join(__dirname, 'static');
const staticFileExtensions = ['.html', '.css', '.js'];
async function readStaticFile(fileName) {
const filePath = path.join(staticDir, fileName);
const buffer = await readFile(filePath);
return buffer;
}
function getMimeType(fileExtension) {
switch (fileExtension) {
case '.html':
return 'text/html';
case '.css':
return 'text/css';
case '.js':
return 'text/javascript';
default:
return 'text/plain';
}
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
*/
async function handler(req, res) {
if (req.method !== 'GET') {
res.statusCode = 403;
res.setHeader('Content-Type', 'text/plain');
res.end('forbidden');
return;
}
const { pathname } = url.parse(req.url);
if (pathname === '/' || pathname === '/index.html') {
const buffer = await readStaticFile('index.html');
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end(buffer);
return;
}
const fileExtension = path.extname(pathname);
if (staticFileExtensions.includes(fileExtension)) {
const buffer = await readStaticFile(pathname);
const mimeType = getMimeType(fileExtension);
res.statusCode = 200;
res.setHeader('Content-Type', mimeType);
res.end(buffer);
return;
}
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('not found');
}
const server = http.createServer(async (req, res) => {
try {
await handler(req, res);
} catch (err) {
console.error(err);
res.statusCode = 500; // eslint-disable-line require-atomic-updates
res.setHeader('Content-Type', 'text/plain');
res.end('internal server error');
}
});
server.listen(port, hostname, () => {
const url = `http://${hostname}:${port}`;
console.log(`Server running at ${url}`);
if (process.platform === 'darwin') {
exec(`open ${url}`, err => {
if (err) {
console.error(err.message);
}
});
} else {
exec(`xdg-open ${url}`, err => {
if (err) {
console.error(err.message);
}
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment