camstreamerlib
Version:
Helper library for CamStreamer ACAP applications.
93 lines (92 loc) • 3.3 kB
JavaScript
import http from 'http';
import url from 'url';
import fs from 'fs';
import path from 'path';
import EventEmitter from 'events';
export class HttpServer extends EventEmitter {
host;
port;
registeredPaths;
server;
sockets;
constructor(options) {
super();
this.host = options?.host ?? process.env.HTTP_HOST ?? '0.0.0.0';
this.port = options?.port ?? parseInt(process.env.HTTP_PORT ?? '80');
this.registeredPaths = new Map();
this.server = http.createServer((req, res) => {
this.emit('access', req.method + ' ' + req.url);
const parsedUrl = url.parse(req.url ?? '');
parsedUrl.pathname ??= '';
const requestCallback = this.registeredPaths.get(parsedUrl.pathname);
if (requestCallback) {
requestCallback(req, res);
return;
}
let pathname = `./html${parsedUrl.pathname}`;
const ext = path.parse(pathname).ext;
const map = {
'.ico': 'image/x-icon',
'.html': 'text/html',
'.js': 'text/javascript',
'.json': 'application/json',
'.css': 'text/css',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.wav': 'audio/wav',
'.mp3': 'audio/mpeg',
'.svg': 'image/svg+xml',
'.pdf': 'application/pdf',
'.doc': 'application/msword',
};
fs.access(pathname, fs.constants.R_OK, (err) => {
if (err) {
res.statusCode = 404;
res.end(`File ${pathname} not found!`);
this.emit('error', `File ${pathname} not found!`);
return;
}
if (fs.statSync(pathname).isDirectory()) {
pathname += `/index${ext}`;
}
fs.readFile(pathname, (error, data) => {
if (error) {
res.statusCode = 500;
res.end(`Error getting the file: ${error}`);
this.emit('error', `Error getting the file: ${error}`);
}
else {
res.setHeader('Content-type', map[ext] ?? 'text/plain');
res.setHeader('Access-Control-Allow-Origin', '*');
res.end(data);
}
});
});
});
this.server.on('error', (err) => {
this.emit('error', err);
});
this.server.listen(this.port, this.host);
this.sockets = {};
let idTracker = 0;
this.server.on('connection', (socket) => {
const socketID = idTracker++;
this.sockets[socketID] = socket;
socket.on('close', () => {
delete this.sockets[socketID];
});
});
}
getServer() {
return this.server;
}
onRequest(pathName, callback) {
this.registeredPaths.set(pathName, callback);
}
close() {
this.server.close();
for (const key in this.sockets) {
this.sockets[key]?.destroy();
}
}
}