From 5d540faec4a99cc168a5a42d549fb08aa726051a Mon Sep 17 00:00:00 2001 From: Mark Oswald Date: Wed, 6 Jul 2016 22:46:55 +0200 Subject: [PATCH] refactor as middleware function and add test --- .../src/Server/__tests__/Server-test.js | 13 ++++++ packager/react-packager/src/Server/index.js | 45 +++++++++---------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/packager/react-packager/src/Server/__tests__/Server-test.js b/packager/react-packager/src/Server/__tests__/Server-test.js index c54e503d171e21..060eb8d2d08f14 100644 --- a/packager/react-packager/src/Server/__tests__/Server-test.js +++ b/packager/react-packager/src/Server/__tests__/Server-test.js @@ -349,6 +349,19 @@ describe('processRequest', () => { expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios'); expect(res.end).toBeCalledWith('i am image'); }); + + it('should serve range request', () => { + const req = {url: '/assets/imgs/a.png?platform=ios', headers: {range: 'bytes=0-3'}}; + const res = {end: jest.fn(), writeHead: jest.fn()}; + const mockData = new Buffer('i am image'); + + AssetServer.prototype.get.mockImpl(() => Promise.resolve(mockData)); + + server.processRequest(req, res); + jest.runAllTimers(); + expect(AssetServer.prototype.get).toBeCalledWith('imgs/a.png', 'ios'); + expect(res.end).toBeCalledWith(mockData.slice(0, 3)); + }); }); describe('buildbundle(options)', () => { diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js index 3cab1e5c948802..1e2d4b1013c29b 100644 --- a/packager/react-packager/src/Server/index.js +++ b/packager/react-packager/src/Server/index.js @@ -169,8 +169,6 @@ const dependencyOpts = declareOpts({ }, }); -const isRangeRequest = (req) => req.headers && req.headers.range; - class Server { constructor(options) { const opts = validateOpts(options); @@ -399,34 +397,33 @@ class Server { }); } + _rangeRequestMiddleware(req, res, data, assetPath) { + if (req.headers && req.headers.range) { + let [rangeStart, rangeEnd] = req.headers.range.replace(/bytes=/, '').split('-'); + let dataStart = parseInt(rangeStart, 10); + let dataEnd = rangeEnd ? parseInt(rangeEnd, 10) : data.length - 1; + let chunksize = (dataEnd - dataStart) + 1; + + res.writeHead(206, { + 'Accept-Ranges': 'bytes', + 'Content-Length': chunksize, + 'Content-Range': `bytes ${dataStart}-${dataEnd}/${data.length}`, + 'Content-Type': mime.lookup(path.basename(assetPath[1])) + }); + + return data.slice(dataStart, dataEnd); + } + + return data; + } + _processAssetsRequest(req, res) { const urlObj = url.parse(req.url, true); const assetPath = urlObj.pathname.match(/^\/assets\/(.+)$/); const assetEvent = Activity.startEvent(`processing asset request ${assetPath[1]}`); this._assetServer.get(assetPath[1], urlObj.query.platform) .then( - data => { - if (isRangeRequest(req)) { - let [rangeStart, rangeEnd] = req.headers.range.replace(/bytes=/, '').split('-'); - let dataStart = parseInt(rangeStart, 10); - let dataEnd = rangeEnd ? parseInt(rangeEnd, 10) : data.length - 1; - let chunksize = (dataEnd - dataStart) + 1; - - res.writeHead(206, { - 'Accept-Ranges': 'bytes', - 'Content-Length': chunksize, - 'Content-Range': `bytes ${dataStart}-${dataEnd}/${data.length}`, - 'Content-Type': mime.lookup(path.basename(assetPath[1])) - }); - - let output = new Buffer(chunksize); - data.copy(output, 0, dataStart, dataEnd); - - res.end(output); - } else { - res.end(data); - } - }, + data => res.end(this._rangeRequestMiddleware(req, res, data, assetPath)), error => { console.error(error.stack); res.writeHead('404');