diff --git a/lib/server/commands/Get.js b/lib/server/commands/Get.js index ce14f73f..ecafc577 100644 --- a/lib/server/commands/Get.js +++ b/lib/server/commands/Get.js @@ -1,6 +1,49 @@ "use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); Object.defineProperty(exports, "__esModule", { value: true }); var WebDAVRequest_1 = require("../WebDAVRequest"); +var stream_1 = require("stream"); +var RangedStream = (function (_super) { + __extends(RangedStream, _super); + function RangedStream(min, max) { + var _this = _super.call(this) || this; + _this.min = min; + _this.max = max; + _this.nb = 0; + return _this; + } + RangedStream.prototype._transform = function (chunk, encoding, callback) { + if (this.nb < this.min) { + this.nb += chunk.length; + if (this.nb > this.min) { + chunk = chunk.slice(this.nb - this.min); + callback(null, chunk); + } + else + callback(null, new Buffer(0)); + } + else if (this.nb > this.max) { + this.nb += chunk.length; + callback(null, new Buffer(0)); + } + else { + this.nb += chunk.length; + if (this.nb > this.max) + chunk = chunk.slice(0, this.max - (this.nb - chunk.length)); + callback(null, chunk); + } + }; + return RangedStream; +}(stream_1.Transform)); function default_1(arg, callback) { arg.noBodyExpected(function () { arg.getResource(function (e, r) { @@ -18,9 +61,23 @@ function default_1(arg, callback) { callback(); } else { - arg.setCode(WebDAVRequest_1.HTTPCodes.OK); - rstream.on('end', callback); - rstream.pipe(arg.response); + var range = arg.findHeader('Range'); + if (range) { + var rex = /([0-9]+)/g; + var min = parseInt(rex.exec(range)[1], 10); + var max = parseInt(rex.exec(range)[1], 10); + arg.setCode(WebDAVRequest_1.HTTPCodes.PartialContent); + arg.response.setHeader('Accept-Ranges', 'bytes'); + arg.response.setHeader('Content-Length', (max - min).toString()); + arg.response.setHeader('Content-Range', 'bytes ' + min + '-' + max + '/*'); + rstream.on('end', callback); + rstream.pipe(new RangedStream(min, max)).pipe(arg.response); + } + else { + arg.setCode(WebDAVRequest_1.HTTPCodes.OK); + rstream.on('end', callback); + rstream.pipe(arg.response); + } } }); }); }); diff --git a/src/server/commands/Get.ts b/src/server/commands/Get.ts index fdcf7cb9..7583144c 100644 --- a/src/server/commands/Get.ts +++ b/src/server/commands/Get.ts @@ -1,6 +1,45 @@ import { HTTPCodes, MethodCallArgs, WebDAVRequest } from '../WebDAVRequest' import { IResource } from '../../resource/IResource' -import { Readable } from 'stream' +import { Readable, Transform } from 'stream' + +class RangedStream extends Transform +{ + nb : number; + + constructor(public min : number, public max : number) + { + super(); + + this.nb = 0; + } + + _transform(chunk: any, encoding: string, callback: Function) + { + if(this.nb < this.min) + { + this.nb += chunk.length; + if(this.nb > this.min) + { + chunk = chunk.slice(this.nb - this.min); + callback(null, chunk); + } + else + callback(null, new Buffer(0)); + } + else if(this.nb > this.max) + { + this.nb += chunk.length; + callback(null, new Buffer(0)); + } + else + { + this.nb += chunk.length; + if(this.nb > this.max) + chunk = chunk.slice(0, this.max - (this.nb - chunk.length)); + callback(null, chunk); + } + } +} export default function(arg : MethodCallArgs, callback) { @@ -25,10 +64,27 @@ export default function(arg : MethodCallArgs, callback) } else { - arg.setCode(HTTPCodes.OK); - - rstream.on('end', callback); - rstream.pipe(arg.response); + const range = arg.findHeader('Range'); + if(range) + { + const rex = /([0-9]+)/g; + const min = parseInt(rex.exec(range)[1], 10); + const max = parseInt(rex.exec(range)[1], 10); + + arg.setCode(HTTPCodes.PartialContent); + arg.response.setHeader('Accept-Ranges', 'bytes') + arg.response.setHeader('Content-Length', (max - min).toString()) + arg.response.setHeader('Content-Range', 'bytes ' + min + '-' + max + '/*') + + rstream.on('end', callback); + rstream.pipe(new RangedStream(min, max)).pipe(arg.response); + } + else + { + arg.setCode(HTTPCodes.OK); + rstream.on('end', callback); + rstream.pipe(arg.response); + } } })) })