Holy-Unblocker/bare/Server.mjs
2022-02-25 22:56:50 -08:00

146 lines
No EOL
3.2 KiB
JavaScript

import { v1, v1socket, v1wsmeta, v1wsnewmeta } from './V1.mjs';
import { Response } from './Response.mjs';
export class Server {
prefix = '/';
fof = this.json(404, { message: 'Not found.' });
maintainer = undefined;
project = {
name: 'TOMPHTTP NodeJS Bare Server',
repository: 'https://github.com/tomphttp/bare-server-node',
};
log_error = false;
constructor(directory, log_error, maintainer){
if(typeof log_error === 'boolean'){
this.log_error = true;
}
if(typeof maintainer === 'object' && maintainer === null){
this.maintainer = maintainer;
}
if(typeof directory !== 'string'){
throw new Error('Directory must be specified.')
}
if(!directory.startsWith('/') || !directory.endsWith('/')){
throw new RangeError('Directory must start and end with /');
}
this.directory = directory;
}
error(...args){
if(this.log_error){
console.error(...args);
}
}
json(status, json){
const send = Buffer.from(JSON.stringify(json, null, '\t'));
return new Response(send, status, {
'content-type': 'application/json',
'content-length': send.byteLength,
});
}
route_request(request, response){
if(request.url.startsWith(this.directory)){
this.request(request, response);
return true;
}else{
return false;
}
}
route_upgrade(request, socket, head){
if(request.url.startsWith(this.directory)){
this.upgrade(request, socket, head);
return true;
}else{
return false;
}
}
get instance_info(){
return {
versions: [ 'v1' ],
language: 'NodeJS',
memoryUsage: Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100,
maintainer: this.maintainer,
developer: this.project,
};
}
async upgrade(request, socket, head){
const service = request.url.slice(this.directory.length - 1);
try{
switch(service){
case'/v1/':
await v1socket(this, request, socket, head);
break;
default:
socket.end();
break;
}
}catch(err){
this.error(err);
socket.end();
}
}
async request(server_request, server_response){
const service = server_request.url.slice(this.directory.length - 1);
let response;
try{
switch(service){
case'/':
if(server_request.method != 'GET')response = this.json(405, { message: 'This route only accepts the GET method.' });
else response = this.json(200, this.instance_info);
break;
case'/v1/':
response = await v1(this, server_request);
break;
case'/v1/ws-meta':
response = await v1wsmeta(this, server_request);
break;
case'/v1/ws-new-meta':
response = await v1wsnewmeta(this, server_request);
break;
default:
response = this.fof;
}
}catch(err){
this.error(err);
if(err instanceof Error){
response = this.json(500, {
code: 'UNKNOWN',
id: `error.${err.name}`,
message: err.message,
stack: err.stack,
});
}else{
response = this.json(500, {
code: 'UNKNOWN',
id: 'error.Exception',
message: err,
stack: new Error(err).stack,
});
}
}
if(!(response instanceof Response)){
this.error('Response to', server_request.url, 'was not a response.');
response = this.fof;
}
response.send(server_response);
}
};