aboutsummaryrefslogtreecommitdiff
path: root/node_modules/koa-range/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/koa-range/index.js')
-rw-r--r--node_modules/koa-range/index.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/node_modules/koa-range/index.js b/node_modules/koa-range/index.js
new file mode 100644
index 00000000..94451f4c
--- /dev/null
+++ b/node_modules/koa-range/index.js
@@ -0,0 +1,105 @@
+
+var util = require('util');
+var slice = require('stream-slice').slice;
+var Stream = require('stream');
+
+module.exports = async function (ctx, next) {
+ var range = ctx.header.range;
+ ctx.set('Accept-Ranges', 'bytes');
+
+ if (!range) {
+ return next();
+ }
+
+ var ranges = rangeParse(range);
+
+ if (!ranges || ranges.length == 0) {
+ ctx.status = 416;
+ return;
+ }
+
+ if (ctx.method == 'PUT') {
+ ctx.status = 400;
+ return;
+ }
+
+ await next();
+
+ if (ctx.method != 'GET' ||
+ ctx.body == null) {
+ return;
+ }
+
+ var first = ranges[0];
+ var rawBody = ctx.body;
+ var len = rawBody.length;
+
+ // avoid multi ranges
+ var firstRange = ranges[0];
+ var start = firstRange[0];
+ var end = firstRange[1];
+
+ if (!Buffer.isBuffer(rawBody)) {
+ if (rawBody instanceof Stream.Readable) {
+ len = ctx.length || '*';
+ rawBody = rawBody.pipe(slice(start, end + 1));
+ } else if (typeof rawBody !== 'string') {
+ rawBody = new Buffer(JSON.stringify(rawBody));
+ len = rawBody.length;
+ } else {
+ rawBody = new Buffer(rawBody);
+ len = rawBody.length;
+ }
+ }
+
+ //Adjust infinite end
+ if (end === Infinity) {
+ if (Number.isInteger(len)) {
+ end = len - 1;
+ } else {
+ // FIXME(Calle Svensson): If we don't know how much we can return, we do a normal HTTP 200 repsonse
+ ctx.status = 200;
+ return;
+ }
+ }
+
+ var args = [start, end+1].filter(function(item) {
+ return typeof item == 'number';
+ });
+
+ ctx.set('Content-Range', rangeContentGenerator(start, end, len));
+ ctx.status = 206;
+
+ if (rawBody instanceof Stream) {
+ ctx.body = rawBody;
+ } else {
+ ctx.body = rawBody.slice.apply(rawBody, args);
+ }
+
+ if (len !== '*') {
+ ctx.length = end - start + 1;
+ }
+};
+
+function rangeParse(str) {
+ var token = str.split('=');
+ if (!token || token.length != 2 || token[0] != 'bytes') {
+ return null;
+ }
+ return token[1].split(',')
+ .map(function(range) {
+ return range.split('-').map(function(value) {
+ if (value === '') {
+ return Infinity;
+ }
+ return Number(value);
+ });
+ })
+ .filter(function(range) {
+ return !isNaN(range[0]) && !isNaN(range[1]) && range[0] <= range[1];
+ });
+}
+
+function rangeContentGenerator(start, end, length) {
+ return util.format('bytes %d-%d/%s', start, end, length);
+}