Files
Kepler/server.js

169 lines
3.3 KiB
JavaScript
Raw Permalink Normal View History

2025-11-17 17:18:43 +01:00
import http from "http";
import { readdir } from "fs/promises";
import { stat } from "fs/promises";
import { readFile } from "fs/promises";
import { join } from "path";
import { dirname } from "path";
import { fileURLToPath } from "url";
class App
{
constructor( )
{
const selfPath = fileURLToPath( import.meta.url );
this.rootPath = dirname( selfPath );
this.httpServer = null;
}
async start( )
{
this.httpServer = http.createServer( this.handleRequest.bind( this ) );
this.httpServer.listen( 4000 );
console.log("server started on port 4000");
}
async handleRequest( req, res )
{
const requestedPath = decodeURI( req.url );
const fullPath = join( this.rootPath, requestedPath );
const exists = await this.checkFileExists( fullPath );
if ( !exists )
{
res.statusCode = 404;
res.end( "Not Found" );
return;
}
const stats = await stat( fullPath );
if ( stats.isDirectory( ) )
{
const indexPath = join( fullPath, "index.html" );
const indexExists = await this.checkFileExists( indexPath );
if ( indexExists )
{
await this.sendFile( indexPath, res );
return;
}
await this.sendDirectoryListing( fullPath, requestedPath, res );
return;
}
await this.sendFile( fullPath, res );
}
async sendFile( path, res )
{
const contentType = this.getContentType( path );
const fileData = await readFile( path );
res.setHeader( "Content-Type", contentType );
res.statusCode = 200;
res.end( fileData );
}
async sendDirectoryListing( dirPath, urlPath, res )
{
const entries = await readdir( dirPath, { withFileTypes : true } );
let html = "<html><body><h1>Index of " + urlPath + "</h1><ul>";
let i = 0;
while ( i < entries.length )
{
const e = entries[ i ].name;
const link = urlPath.endsWith( "/" )
? urlPath + e
: urlPath + "/" + e;
html = html + "<li><a href=\"" + link + "\">" + e + "</a></li>";
i = i + 1;
}
html = html + "</ul></body></html>";
res.setHeader( "Content-Type", "text/html" );
res.statusCode = 200;
res.end( html );
}
async checkFileExists( path )
{
const exists = await stat( path )
.then( function( ) { return true; } )
.catch( function( ) { return false; } );
return exists;
}
getContentType( path )
{
const lower = path.toLowerCase( );
if ( lower.endsWith( ".html" ) ) return "text/html";
if ( lower.endsWith( ".css" ) ) return "text/css";
if ( lower.endsWith( ".js" ) ) return "text/javascript";
if ( lower.endsWith( ".json" ) ) return "application/json";
if ( lower.endsWith( ".wasm" ) ) return "application/wasm";
if ( lower.endsWith( ".png" ) ) return "image/png";
if ( lower.endsWith( ".jpg" ) ) return "image/jpeg";
if ( lower.endsWith( ".jpeg" ) ) return "image/jpeg";
if ( lower.endsWith( ".gif" ) ) return "image/gif";
if ( lower.endsWith( ".svg" ) ) return "image/svg+xml";
if ( lower.endsWith( ".wgsl" ) ) return "text/plain";
if ( lower.endsWith( ".txt" ) ) return "text/plain";
return "application/octet-stream";
}
}
const app = new App( );
await app.start( );