Browse Source

any error with partial response is a Partial Error

Gil Pedersen 13 năm trước cách đây
mục cha
commit
279bf24e0f
1 tập tin đã thay đổi với 19 bổ sung6 xóa
  1. 19 6
      lib/uristream.js

+ 19 - 6
lib/uristream.js

@@ -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;
 }