diff --git a/lib/server/main.js b/lib/server/main.js index 47e8bf0a..431dd8d7 100644 --- a/lib/server/main.js +++ b/lib/server/main.js @@ -10,10 +10,10 @@ SLASH, ISWIN32, - ext, + ext, dir, parseRange, path, fs, zlib, url, pipe, CloudFunc, diffPatch, querystring, time, - OK, FILE_NOT_FOUND, MOVED_PERMANENTLY, + OK, RANGE, FILE_NOT_FOUND, MOVED_PERMANENTLY, REQUEST, RESPONSE, Config = { @@ -25,6 +25,7 @@ /* Consts */ exports.OK = OK = 200; + RANGE = 206; MOVED_PERMANENTLY = 301; exports.FILE_NOT_FOUND = FILE_NOT_FOUND = 404; @@ -110,10 +111,11 @@ exports.express = srvrequire('express'), exports.auth = srvrequire('auth').auth, exports.appcache = srvrequire('appcache'), - exports.dir = srvrequire('dir'), + exports.dir = dir = srvrequire('dir'), exports.hash = srvrequire('hash'), diffPatch = librequire('diff/diff-match-patch').diff_match_patch, exports.diff = new (librequire('diff').DiffProto)(diffPatch), + parseRange = srvrequire('parse-range'); exports.time = time = srvrequire('time'); exports.users = srvrequire('users'); exports.rest = srvrequire('rest').api, @@ -207,7 +209,7 @@ encoding = ''; /* if type of file any, but img - then we shoud specify charset */ - isContain = Util.isContainStr(type, ['img', 'image']); + isContain = Util.isContainStr(type, ['img', 'image', 'audio']); if (!isContain) encoding = '; charset=UTF-8'; @@ -218,12 +220,23 @@ header = { 'Access-Control-Allow-Origin' : '*', 'Content-Type' : type + encoding, - 'Vary' : 'Accept-Encoding' + 'Vary' : 'Accept-Encoding', + 'Accept-Ranges' : 'bytes' }; - if (p.time) { - header['Last-Modified'] = p.time; - } + if (p.time) + Util.copyObj(header, { + 'Last-Modified' : p.time + }); + + if (p.range) + Util.copyObj(header, { + 'Content-Range' : 'bytes ' + p.range.start + + '-' + p.range.end + + '/' + p.length, + + 'Content-Length': p.range.size + }); cmp = Util.strCmp(ext, '.appcache'); if (!cmp && p.cache) @@ -247,6 +260,8 @@ header = generateHeaders({ name : p.name, time : p.time, + range : p.range, + length : p.length, cache : p.cache, gzip : lGzip, query : getQuery(p.request) @@ -265,32 +280,44 @@ * @param pGzip - данные сжаты gzip'ом */ function sendFile(params) { - var isGzip, getTime, + var isGzip, getTime, getSize, ext, p = params, ret = checkParams(params); if (ret) { isGzip = isGZIP(p.request) && p.gzip; + ext = Util.getExtension(p.name); getTime = Util.bind(time.get, p.name, { str: true }); - getTime(function(error, time) { - if (error) { + getSize = Util.bind(dir.getSize, p.name); + + Util.asyncCall([getTime, getSize], function(timeData, sizeData) { + var error = timeData[0] || sizeData[0], + time = timeData[1], + length = sizeData[1], + range = getRange(p.request, length); + + if (error) { sendError(params, error); } else { Util.copyObj(p, { - isGzip : isGzip, - time : time + isGzip : isGzip && !range, + time : time, + range : range, + length : length, + status : range ? RANGE : OK }); mainSetHeader(params); - + pipe.create({ from : p.name, write : p.response, - gzip : isGzip, + gzip : isGzip && !range, + range : range, callback: function(error) { if (error) sendError(params, error); @@ -454,4 +481,23 @@ response.setHeader(name, header[name]); } + function getRange(req, totalSize) { + var range, start, end, size, parts, + rangeStr = req.headers.range; + console.log(rangeStr) + if (rangeStr) { + parts = rangeStr.replace(/bytes=/, "").split("-"); + start = parts[0]; + end = parts[1] || totalSize - 1; + size = (end - start) + 1; + + range = { + start : start - 0, + end : end - 0, + size : size + }; + } + + return range; + } })();