2024-08-23 19:58:15 +02:00
const http = require ( "http" ) ;
const fs = require ( "fs" ) ;
const cluster = require ( "./utils/clusterBunShim.js" ) ; // Cluster module with shim for Bun
2024-08-23 20:43:09 +02:00
//const generateErrorStack = require("./utils/generateErrorStack.js");
2024-08-23 19:58:15 +02:00
const getOS = require ( "./utils/getOS.js" ) ;
const svrjsInfo = require ( "../svrjs.json" ) ;
const version = svrjsInfo . version ;
//const parseURL = require("./utils/urlParser.js");
//const fixNodeMojibakeURL = require("./utils/urlMojibakeFixer.js");
2024-08-23 21:58:26 +02:00
let inspector = undefined ;
try {
inspector = require ( "inspector" ) ;
} catch ( err ) {
// Don't use inspector
}
2024-08-23 19:58:15 +02:00
// Create log, mods and temp directories, if they don't exist.
if ( ! fs . existsSync ( _ _dirname + "/log" ) ) fs . mkdirSync ( _ _dirname + "/log" ) ;
if ( ! fs . existsSync ( _ _dirname + "/mods" ) ) fs . mkdirSync ( _ _dirname + "/mods" ) ;
if ( ! fs . existsSync ( _ _dirname + "/temp" ) ) fs . mkdirSync ( _ _dirname + "/temp" ) ;
const serverconsoleConstructor = require ( "./utils/serverconsole.js" ) ;
2024-08-23 21:58:26 +02:00
let inspectorURL = undefined ;
try {
if ( inspector ) {
inspectorURL = inspector . url ( ) ;
}
} catch ( err ) {
// Failed to get inspector URL
}
if ( ! process . stdout . isTTY && ! inspectorURL ) {
// When stdout is not a terminal and not attached to an Node.JS inspector, disable it to improve performance of SVR.JS
console . log = function ( ) { } ;
process . stdout . write = function ( ) { } ;
process . stdout . _write = function ( ) { } ;
process . stdout . _writev = function ( ) { } ;
}
2024-08-23 20:43:09 +02:00
let configJSON = { } ;
2024-08-23 19:58:15 +02:00
// TODO: configuration from config.json
2024-08-23 21:33:26 +02:00
if ( configJSON . users === undefined ) configJSON . users = [ ] ;
if ( configJSON . secure ) {
if ( configJSON . key === undefined ) configJSON . key = "cert/key.key" ;
if ( configJSON . cert === undefined ) configJSON . cert = "cert/cert.crt" ;
if ( configJSON . sport === undefined ) configJSON . sport = 443 ;
if ( configJSON . spubport === undefined ) configJSON . spubport = 443 ;
if ( configJSON . sni === undefined ) configJSON . sni = { } ;
if ( configJSON . enableOCSPStapling === undefined ) configJSON . enableOCSPStapling = false ;
}
if ( configJSON . port === undefined ) configJSON . port = 80 ;
if ( configJSON . pubport === undefined ) configJSON . pubport = 80 ;
if ( configJSON . domain === undefined && configJSON . domian !== undefined ) configJSON . domain = configJSON . domian ;
delete configJSON . domian ;
if ( configJSON . page404 === undefined ) configJSON . page404 = "404.html" ;
//configJSON.timestamp = timestamp; //TODO
//configJSON.blacklist = blocklist.raw; //TODO
if ( configJSON . nonStandardCodes === undefined ) configJSON . nonStandardCodes = [ ] ;
if ( configJSON . enableCompression === undefined ) configJSON . enableCompression = true ;
if ( configJSON . customHeaders === undefined ) configJSON . customHeaders = { } ;
if ( configJSON . enableHTTP2 === undefined ) configJSON . enableHTTP2 = false ;
if ( configJSON . enableLogging === undefined ) configJSON . enableLogging = true ;
if ( configJSON . enableDirectoryListing === undefined ) configJSON . enableDirectoryListing = true ;
if ( configJSON . enableDirectoryListingWithDefaultHead === undefined ) configJSON . enableDirectoryListingWithDefaultHead = false ;
if ( configJSON . serverAdministratorEmail === undefined ) configJSON . serverAdministratorEmail = "[no contact information]" ;
if ( configJSON . stackHidden === undefined ) configJSON . stackHidden = false ;
if ( configJSON . enableRemoteLogBrowsing === undefined ) configJSON . enableRemoteLogBrowsing = false ;
if ( configJSON . exposeServerVersion === undefined ) configJSON . exposeServerVersion = true ;
if ( configJSON . disableServerSideScriptExpose === undefined ) configJSON . disableServerSideScriptExpose = true ;
if ( configJSON . allowStatus === undefined ) configJSON . allowStatus = true ;
if ( configJSON . rewriteMap === undefined ) configJSON . rewriteMap = [ ] ;
if ( configJSON . dontCompress === undefined ) configJSON . dontCompress = [ "/.*\\.ipxe$/" , "/.*\\.(?:jpe?g|png|bmp|tiff|jfif|gif|webp)$/" , "/.*\\.(?:[id]mg|iso|flp)$/" , "/.*\\.(?:zip|rar|bz2|[gb7x]z|lzma|tar)$/" , "/.*\\.(?:mp[34]|mov|wm[av]|avi|webm|og[gv]|mk[va])$/" ] ;
if ( configJSON . enableIPSpoofing === undefined ) configJSON . enableIPSpoofing = false ;
if ( configJSON . secure === undefined ) configJSON . secure = false ;
if ( configJSON . disableNonEncryptedServer === undefined ) configJSON . disableNonEncryptedServer = false ;
if ( configJSON . disableToHTTPSRedirect === undefined ) configJSON . disableToHTTPSRedirect = false ;
if ( configJSON . enableETag === undefined ) configJSON . enableETag = true ;
if ( configJSON . disableUnusedWorkerTermination === undefined ) configJSON . disableUnusedWorkerTermination = false ;
if ( configJSON . rewriteDirtyURLs === undefined ) configJSON . rewriteDirtyURLs = false ;
if ( configJSON . errorPages === undefined ) configJSON . errorPages = [ ] ;
if ( configJSON . useWebRootServerSideScript === undefined ) configJSON . useWebRootServerSideScript = true ;
if ( configJSON . exposeModsInErrorPages === undefined ) configJSON . exposeModsInErrorPages = true ;
if ( configJSON . disableTrailingSlashRedirects === undefined ) configJSON . disableTrailingSlashRedirects = false ;
if ( configJSON . environmentVariables === undefined ) configJSON . environmentVariables = { } ;
2024-08-24 08:02:11 +02:00
if ( configJSON . wwwrootPostfixesVHost === undefined ) configJSON . wwwrootPostfixesVHost = [ ] ;
if ( configJSON . wwwrootPostfixPrefixesVHost === undefined ) configJSON . wwwrootPostfixPrefixesVHost = [ ] ;
2024-08-23 21:33:26 +02:00
if ( configJSON . allowDoubleSlashes === undefined ) configJSON . allowDoubleSlashes = false ;
2024-08-24 08:02:11 +02:00
if ( configJSON . allowPostfixDoubleSlashes === undefined ) configJSON . allowPostfixDoubleSlashes = false ;
2024-08-23 21:33:26 +02:00
if ( configJSON . optOutOfStatisticsServer === undefined ) configJSON . optOutOfStatisticsServer = false ;
configJSON . version = version ; // Compatiblity for very old SVR.JS mods
var wwwrootError = null ;
try {
if ( cluster . isPrimary || cluster . isPrimary === undefined ) process . chdir ( configJSON . wwwroot != undefined ? configJSON . wwwroot : _ _dirname ) ;
} catch ( err ) {
wwwrootError = err ;
}
2024-08-23 20:43:09 +02:00
const serverconsole = serverconsoleConstructor ( configJSON . enableLogging ) ;
let middleware = [
2024-08-23 21:25:23 +02:00
require ( "./middleware/core.js" ) ,
2024-08-23 22:13:58 +02:00
require ( "./middleware/urlSanitizer.js" ) ,
2024-08-24 08:02:11 +02:00
require ( "./middleware/redirects.js" ) ,
2024-08-24 08:22:49 +02:00
require ( "./middleware/webRootPostfixes.js" ) ,
require ( "./middleware/rewriteURL.js" )
2024-08-23 20:43:09 +02:00
] ;
function addMiddleware ( mw ) {
middleware . push ( mw ) ;
2024-08-23 19:58:15 +02:00
}
function requestHandler ( req , res ) {
let reqIdInt = Math . floor ( Math . random ( ) * 16777216 ) ;
if ( reqIdInt == 16777216 ) reqIdInt = 0 ;
const reqId = "0" . repeat ( 6 - reqIdInt . toString ( 16 ) . length ) + reqIdInt . toString ( 16 ) ;
// SVR.JS log facilities
const logFacilities = {
climessage : ( msg ) => serverconsole . climessage ( msg , reqId ) ,
reqmessage : ( msg ) => serverconsole . reqmessage ( msg , reqId ) ,
resmessage : ( msg ) => serverconsole . resmessage ( msg , reqId ) ,
errmessage : ( msg ) => serverconsole . errmessage ( msg , reqId ) ,
locerrmessage : ( msg ) => serverconsole . locerrmessage ( msg , reqId ) ,
locwarnmessage : ( msg ) => serverconsole . locwarnmessage ( msg , reqId ) ,
locmessage : ( msg ) => serverconsole . locmessage ( msg , reqId )
} ;
2024-08-23 20:43:09 +02:00
// SVR.JS configuration object (modified)
const config = Object . assign ( configJSON ) ;
2024-08-23 19:58:15 +02:00
2024-08-23 20:43:09 +02:00
let index = 0 ;
2024-08-23 19:58:15 +02:00
2024-08-23 20:43:09 +02:00
// Call the next middleware function
const next = ( ) => {
const currentMiddleware = middleware [ index ++ ] ;
if ( currentMiddleware ) {
try {
currentMiddleware ( req , res , logFacilities , config , next ) ;
} catch ( err ) {
2024-08-23 21:25:23 +02:00
if ( res . error ) res . error ( 500 , err ) ;
2024-08-23 19:58:15 +02:00
else {
2024-08-23 21:25:23 +02:00
logFacilities . errmessage ( "There was an error while processing the request!" ) ;
logFacilities . errmessage ( "Stack:" ) ;
logFacilities . errmessage ( err . stack ) ;
2024-08-23 20:43:09 +02:00
res . writeHead ( 500 , "Internal Server Error" , {
Server : ( config . exposeServerVersion ? "SVR.JS/" + version + " (" + getOS ( ) + "; " + ( process . isBun ? ( "Bun/v" + process . versions . bun + "; like Node.JS/" + process . version ) : ( "Node.JS/" + process . version ) ) + ")" : "SVR.JS" )
} ) ;
res . end ( "Error while executing the request handler" ) ;
2024-08-23 19:58:15 +02:00
}
}
2024-08-23 20:43:09 +02:00
} else {
if ( res . error ) res . error ( 404 ) ;
else {
res . writeHead ( 404 , "Not Found" , {
Server : ( config . exposeServerVersion ? "SVR.JS/" + version + " (" + getOS ( ) + "; " + ( process . isBun ? ( "Bun/v" + process . versions . bun + "; like Node.JS/" + process . version ) : ( "Node.JS/" + process . version ) ) + ")" : "SVR.JS" )
2024-08-23 19:58:15 +02:00
} ) ;
2024-08-23 20:43:09 +02:00
res . end ( "Request handler missing" ) ;
2024-08-23 19:58:15 +02:00
}
}
}
2024-08-23 20:43:09 +02:00
// Handle middleware
next ( ) ;
2024-08-23 19:58:15 +02:00
}
// Create HTTP server
http . createServer ( requestHandler ) . listen ( 3000 ) ;
2024-08-23 21:34:58 +02:00
2024-08-23 21:35:58 +02:00
if ( wwwrootError ) throw wwwrootError ;