Last active
April 1, 2024 04:10
-
-
Save stif/f063d2807556d18a786369425758cbc4 to your computer and use it in GitHub Desktop.
node.js HTTP Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as http from 'http' | |
import { URL } from 'url' | |
import { stat, readFile } from 'fs/promises'; | |
import { join, extname } from 'path'; | |
// you can pass the parameter in the command line. e.g. node http_server.js 3000 | |
const port = process.argv[2] || 9000; | |
// maps file extention to MIME types | |
// full list can be found here: https://www.freeformatter.com/mime-types-list.html | |
const mimeType = { | |
'.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', | |
'.zip': 'application/zip', | |
'.doc': 'application/msword', | |
'.eot': 'application/vnd.ms-fontobject', | |
'.ttf': 'application/x-font-ttf', | |
}; | |
let webserver = http.createServer( async (req, res) => { | |
console.log(`${req.method} ${req.url}`); | |
//console.log("Request Headers: " + JSON.stringify(req.headers, null, '\t')); | |
// parse URL | |
const baseURL = 'http://' + req.headers.host + '/'; | |
const parsedUrl = new URL(req.url, baseURL); | |
let pathname = decodeURIComponent(join('../frontend/dist', parsedUrl.pathname)); | |
try { | |
let stats = await stat(pathname) | |
if(stats.isDirectory()) { | |
pathname += '/index.html'; | |
} | |
// if the file is found, read it and its extension | |
const data = await readFile(pathname) | |
const ext = extname(pathname) | |
// set Content-type and send data | |
res.setHeader('Content-type', mimeType[ext] || 'text/plain' ); | |
res.end(data); | |
} | |
catch (err) { | |
// if the file is not found, return 404 | |
if(err.code == 'ENOENT') { | |
console.error(`file ${pathname} does not exist / stats undefined`) | |
res.statusCode = 404; | |
res.end(`File ${pathname} not found!`); | |
} | |
else { | |
console.error("Error: " + err.message) | |
res.statusCode = 500; | |
res.end(`Error getting the file: ${err}.`); | |
} | |
} | |
}) | |
webserver.listen(port); | |
console.log(`Server listening on port ${port}`); | |
//export { webserver }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there! I've modified this gist to use https and it works pretty much the same way. One thing to note is that the gist (as well as my https version of the gist) will fail and crash a running website if
req.headers.host
contains unsafe characters (which I found happens to me because CloudFlare was injecting its ownreq.headers.host
requests; more specifically the string-{ip}:{host}
). I've replacedreq.headers.host
with to fix the error instead of catching it and handling it. Essentially, the (potentially malformed/injected) host header string is regex parsed against all unsafe characters and replaces it with '.' to force it to validate and then the rest of your code takes care of the possible file-not-found condition. This is what I used to resolve the issue but may not be the correct remedy. Either way, I hope this is useful to you or others looking at the gist and was the reason for my comment. Thanks!