|
|
@@ -55,6 +55,7 @@ function setupHttp(uri, options, dst) {
|
|
|
else
|
|
|
delete headers['range'];
|
|
|
|
|
|
+ var accum = 0, size = -1;
|
|
|
var req = fetch({uri:uri, pool:false, headers:headers, timeout:timeout});
|
|
|
req.on('error', onreqerror);
|
|
|
req.on('error', noop);
|
|
|
@@ -62,6 +63,9 @@ function setupHttp(uri, options, dst) {
|
|
|
|
|
|
function failOrRetry(err, temporary) {
|
|
|
req.abort();
|
|
|
+ // remap error to partial error if we have received any data
|
|
|
+ if (start + accum !== 0)
|
|
|
+ err = new PartialError(err, start - offset + accum, (size !== -1) ? start - offset + size : size);
|
|
|
return dst.emit('error', err);
|
|
|
}
|
|
|
|
|
|
@@ -81,7 +85,7 @@ function setupHttp(uri, options, dst) {
|
|
|
if (res.statusCode !== 200 && res.statusCode !== 206)
|
|
|
return failOrRetry(new Error('Bad server response code: '+res.statusCode), res.statusCode >= 500 && res.statusCode !== 501);
|
|
|
|
|
|
- var size = res.headers['content-length'] ? parseInt(res.headers['content-length'], 10) : -1;
|
|
|
+ if (res.headers['content-length']) size = parseInt(res.headers['content-length'], 10);
|
|
|
var filesize = (size >= 0) ? start + size - offset : -1;
|
|
|
|
|
|
// transparently handle gzip responses
|
|
|
@@ -117,7 +121,6 @@ function setupHttp(uri, options, dst) {
|
|
|
|
|
|
// turn bad content-length into actual errors
|
|
|
if (size >= 0 && !probe) {
|
|
|
- var accum = 0;
|
|
|
res.on('data', function(chunk) {
|
|
|
accum += chunk.length;
|
|
|
if (accum > size)
|
|
|
@@ -126,7 +129,7 @@ function setupHttp(uri, options, dst) {
|
|
|
|
|
|
oncemore(res).once('end', 'error', function(err) {
|
|
|
if (!err && accum !== size)
|
|
|
- failOrRetry(new PartialError('Stream length did not match header', accum, size), accum && accum < size);
|
|
|
+ failOrRetry(new Error('Stream length did not match header'), accum && accum < size);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -172,9 +175,19 @@ function uristream(uri, options) {
|
|
|
return new UriFetchStream(uri, options);
|
|
|
}
|
|
|
|
|
|
-function PartialError(msg, processed, expected) {
|
|
|
- Error.captureStackTrace(this, this);
|
|
|
- this.message = msg || 'PartialError';
|
|
|
+function PartialError(err, processed, expected) {
|
|
|
+ Error.call(this);
|
|
|
+
|
|
|
+ if (err.stack) {
|
|
|
+ Object.defineProperty(this, 'stack', {
|
|
|
+ enumerable: false,
|
|
|
+ configurable: false,
|
|
|
+ get: function() { return err.stack; }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else Error.captureStackTrace(this, arguments.callee);
|
|
|
+
|
|
|
+ this.message = err.message || err.toString();
|
|
|
this.processed = processed || -1;
|
|
|
this.expected = expected;
|
|
|
}
|