aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/server.js47
-rw-r--r--src/server/HttpServer.hx49
2 files changed, 65 insertions, 31 deletions
diff --git a/build/server.js b/build/server.js
index 63ed3f4..5555428 100644
--- a/build/server.js
+++ b/build/server.js
@@ -3482,9 +3482,15 @@ server_HttpServer.serveFiles = function(req,res) {
url = "/index.html";
}
var filePath = server_HttpServer.dir + url;
+ var ext = haxe_io_Path.extension(filePath).toLowerCase();
+ res.setHeader("Accept-Ranges","bytes");
+ res.setHeader("Content-Type",server_HttpServer.getMimeType(ext));
if(server_HttpServer.allowLocalRequests && req.connection.remoteAddress == req.connection.localAddress || server_HttpServer.allowedLocalFiles.h[url]) {
- if(server_HttpServer.serveLocalFile(res,url)) {
- return;
+ if(server_HttpServer.isMediaExtension(ext)) {
+ server_HttpServer.allowedLocalFiles.h[url] = true;
+ if(server_HttpServer.serveMedia(req,res,url)) {
+ return;
+ }
}
}
if(!server_HttpServer.isChildOf(server_HttpServer.dir,filePath)) {
@@ -3508,13 +3514,16 @@ server_HttpServer.serveFiles = function(req,res) {
}
}
}
+ if(server_HttpServer.isMediaExtension(ext)) {
+ if(server_HttpServer.serveMedia(req,res,filePath)) {
+ return;
+ }
+ }
js_node_Fs.readFile(filePath,function(err,data) {
if(err != null) {
server_HttpServer.readFileError(err,res,filePath);
return;
}
- var ext = haxe_io_Path.extension(filePath).toLowerCase();
- res.setHeader("Content-Type",server_HttpServer.getMimeType(ext));
if(ext == "html") {
data = server_HttpServer.localizeHtml(data.toString(),req.headers["accept-language"]);
}
@@ -3530,25 +3539,31 @@ server_HttpServer.readFileError = function(err,res,filePath) {
res.end("Error getting the file: " + Std.string(err) + ".");
}
};
-server_HttpServer.serveLocalFile = function(res,filePath) {
- var ext = haxe_io_Path.extension(filePath).toLowerCase();
- if(ext != "mp4" && ext != "mp3" && ext != "wav") {
+server_HttpServer.serveMedia = function(req,res,filePath) {
+ var range = req.headers["range"];
+ if(range == null) {
return false;
}
if(!js_node_Fs.existsSync(filePath)) {
return false;
}
- server_HttpServer.allowedLocalFiles.h[filePath] = true;
- js_node_Fs.readFile(filePath,function(err,data) {
- if(err != null) {
- server_HttpServer.readFileError(err,res,filePath);
- return;
- }
- res.setHeader("Content-Type",server_HttpServer.getMimeType(ext));
- res.end(data);
- });
+ var videoSize = js_node_Fs.statSync(filePath).size;
+ var _this_r = new RegExp("[^0-9]","g".split("u").join(""));
+ var start = Std.parseInt(range.replace(_this_r,""));
+ var end = Math.min(start + 5242880,videoSize - 1) | 0;
+ res.setHeader("Content-Range","bytes " + start + "-" + end + "/" + videoSize);
+ res.setHeader("Content-Length","" + (end - start + 1));
+ res.statusCode = 206;
+ js_node_Fs.createReadStream(filePath,{ start : start, end : end}).pipe(res);
return true;
};
+server_HttpServer.isMediaExtension = function(ext) {
+ if(!(ext == "mp4" || ext == "mp3")) {
+ return ext == "wav";
+ } else {
+ return true;
+ }
+};
server_HttpServer.localizeHtml = function(data,lang) {
if(lang != null && server_HttpServer.matchLang.match(lang)) {
lang = server_HttpServer.matchLang.matched(0);
diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx
index 0388c28..46540a3 100644
--- a/src/server/HttpServer.hx
+++ b/src/server/HttpServer.hx
@@ -53,10 +53,17 @@ class HttpServer {
var url = req.url;
if (url == "/") url = "/index.html";
var filePath = dir + url;
+ final ext = Path.extension(filePath).toLowerCase();
+
+ res.setHeader("Accept-Ranges", "bytes");
+ res.setHeader("Content-Type", getMimeType(ext));
if (allowLocalRequests && req.connection.remoteAddress == req.connection.localAddress
|| allowedLocalFiles[url]) {
- if (serveLocalFile(res, url)) return;
+ if (isMediaExtension(ext)) {
+ allowedLocalFiles[url] = true;
+ if (serveMedia(req, res, url)) return;
+ }
}
if (!isChildOf(dir, filePath)) {
@@ -81,13 +88,15 @@ class HttpServer {
}
}
+ if (isMediaExtension(ext)) {
+ if (serveMedia(req, res, filePath)) return;
+ }
+
Fs.readFile(filePath, (err:Dynamic, data:Buffer) -> {
if (err != null) {
readFileError(err, res, filePath);
return;
}
- final ext = Path.extension(filePath).toLowerCase();
- res.setHeader("Content-Type", getMimeType(ext));
if (ext == "html") {
// replace ${textId} to localized strings
data = cast localizeHtml(data.toString(), req.headers["accept-language"]);
@@ -107,22 +116,32 @@ class HttpServer {
}
}
- static function serveLocalFile(res:ServerResponse, filePath:String):Bool {
- final ext = Path.extension(filePath).toLowerCase();
- if (ext != "mp4" && ext != "mp3" && ext != "wav") return false;
+ static function serveMedia(req:IncomingMessage, res:ServerResponse, filePath:String):Bool {
+ final range:String = req.headers["range"];
+ if (range == null) return false;
if (!Fs.existsSync(filePath)) return false;
- allowedLocalFiles[filePath] = true;
- Fs.readFile(filePath, (err:Dynamic, data:Buffer) -> {
- if (err != null) {
- readFileError(err, res, filePath);
- return;
- }
- res.setHeader("Content-Type", getMimeType(ext));
- res.end(data);
- });
+ final videoSize = Fs.statSync(filePath).size;
+ // range example: "bytes=24182784-"
+ final CHUNK_SIZE = 1024 * 1024 * 5; // 5 MB
+ final start = Std.parseInt(~/[^0-9]/g.replace(range, ""));
+ final end = Std.int(Math.min(start + CHUNK_SIZE, videoSize - 1));
+ final contentLength = end - start + 1;
+
+ res.setHeader("Content-Range", 'bytes ${start}-${end}/${videoSize}');
+ res.setHeader("Content-Length", '$contentLength');
+ // HTTP Status 206 for Partial Content
+ res.statusCode = 206;
+ // create video read stream for this particular chunk
+ final videoStream = Fs.createReadStream(filePath, {start: start, end: end});
+ // stream the video chunk to the client
+ videoStream.pipe(res);
return true;
}
+ static function isMediaExtension(ext:String):Bool {
+ return ext == "mp4" || ext == "mp3" || ext == "wav";
+ }
+
static final matchLang = ~/^[A-z]+/;
static final matchVarString = ~/\${([A-z_]+)}/g;
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage