diff options
| author | RblSb <msrblsb@gmail.com> | 2020-02-13 16:28:18 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2020-02-15 19:45:40 +0300 |
| commit | 07d1955cefc093ffb12002902ed45e963030746e (patch) | |
| tree | 8833eca2dc2ef07891aa8eb66daf7ad90f2ab0ce /src/server/HttpServer.hx | |
Initial commit
Diffstat (limited to 'src/server/HttpServer.hx')
| -rw-r--r-- | src/server/HttpServer.hx | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx new file mode 100644 index 0000000..b49301b --- /dev/null +++ b/src/server/HttpServer.hx @@ -0,0 +1,106 @@ +package server; + +import js.node.Buffer; +import haxe.io.Path; +import js.node.Fs; +import sys.io.File; +import js.node.http.IncomingMessage; +import js.node.http.ServerResponse; +import js.Node.__dirname; +import js.node.Path as JsPath; +using StringTools; + +class HttpServer { + + static final mimeTypes = [ + "html" => "text/html", + "js" => "text/javascript", + "css" => "text/css", + "json" => "application/json", + "png" => "image/png", + "jpg" => "image/jpg", + "gif" => "image/gif", + "svg" => "image/svg+xml", + "ico" => "image/x-icon", + "wav" => "audio/wav", + "mp3" => "audio/mpeg", + "mp4" => "video/mp4", + "woff" => "application/font-woff", + "ttf" => "application/font-ttf", + "eot" => "application/vnd.ms-fontobject", + "otf" => "application/font-otf", + "wasm" => "application/wasm" + ]; + + static var dir:String; + + public static function init(directory:String):Void { + dir = directory; + } + + public static function serveFiles(req:IncomingMessage, res:ServerResponse):Void { + var filePath = dir + req.url; + if (req.url == "/") filePath = '$dir/index.html'; + + final extension = Path.extension(filePath).toLowerCase(); + final contentType = getMimeType(extension); + + if (!isChildOf(dir, filePath)) { + res.statusCode = 500; + var rel = JsPath.relative(dir, filePath); + res.end('Error getting the file: No access to $rel.'); + return; + } + + // load client code from build folder + if (filePath == '$dir/client.js') { + filePath = '$__dirname/client.js'; + } + + Fs.readFile(filePath, function(err:Dynamic, data:Buffer) { + if (err != null) { + if (err.code == "ENOENT") { + res.statusCode = 404; + var rel = JsPath.relative(dir, filePath); + res.end('File $rel not found.'); + } else { + res.statusCode = 500; + res.end('Error getting the file: $err.'); + } + return; + } + res.setHeader("Content-Type", contentType); + if (extension == "html") { + // replace ${textId} to localized strings + data = cast localizeHtml(data.toString(), req.headers["accept-language"]); + } + res.end(data); + }); + } + + static final matchLang = ~/^[A-z]+/; + + static function localizeHtml(data:String, lang:String):String { + if (lang != null && matchLang.match(lang)) { + lang = matchLang.matched(0); + } else lang = "en"; + data = ~/\${([A-z_]+)}/g.map(data, (regExp) -> { + final key = regExp.matched(1); + return Lang.get(lang, key); + }); + return data; + } + + static function isChildOf(parent:String, child:String):Bool { + final path = JsPath; + final relative = path.relative(parent, child); + return relative.length > 0 && !relative.startsWith('..') && !path.isAbsolute(relative); + } + + static function getMimeType(ext:String):String { + var contentType = mimeTypes[ext]; + if (contentType == null) contentType = "application/octet-stream"; + return contentType; + } + +} |
