Compare commits

...

55 Commits

Author SHA1 Message Date
John Hiesey 80ef3ca4ed Improve test reliability and bump deps 2021-04-13 22:29:31 -07:00
John Hiesey a2ba46d0ab Also support opts.timeout 2021-04-13 21:05:59 -07:00
John Hiesey 2c44eeb142 Update readme 2021-04-13 17:12:33 -07:00
John Hiesey 2572062eae Add timeout test 2021-04-13 16:27:08 -07:00
John Hiesey 681541d968 Emit error on destroy(err) 2021-04-13 16:23:47 -07:00
John Hiesey 54f5c2caae Add ClientRequest.setTimeout 2021-04-13 14:55:08 -07:00
Feross Aboukhadijeh e84db22d08 3.1.1 2020-05-05 10:37:01 -07:00
Feross Aboukhadijeh c05cfbbae8 bump all deps 2020-05-05 09:57:13 -07:00
Feross Aboukhadijeh 0657afd6ce tape@5 2020-05-05 09:57:13 -07:00
Feross Aboukhadijeh 36f13468b4 airtap@3 2020-05-05 09:57:13 -07:00
Feross Aboukhadijeh 0e1f2f30fc Merge pull request #112 from jhiesey/unused-var 2020-05-05 09:54:37 -07:00
Feross Aboukhadijeh f20f3cc30a Merge pull request #114 from cusspvz/patch-1 2020-05-05 09:54:24 -07:00
José Moreira 8320c894b9 fix: typo for the mode prefer-streaming at the readme.md file 2019-10-30 23:20:40 +00:00
Feross Aboukhadijeh 79f7465418 Remove unused variable 2019-08-12 18:16:38 -07:00
Feross Aboukhadijeh a38d9ab491 3.1.0 2019-08-06 19:18:49 -07:00
Feross Aboukhadijeh b81de11325 airtap: test last two chrome, firefox, edge
Speeds up tests considerably

Note to @jhiesey: feel free to change this to test more browsers if you want to, but for the evergreen browsers (chrome, firefox, and soon edge) it seems fine to just test the last two versions since users shouldn't be on any other version. Up to you though :)
2019-08-06 19:18:36 -07:00
Feross Aboukhadijeh 7092c3c95f Delete package-lock.json 2019-08-06 19:02:49 -07:00
Feross Aboukhadijeh 2e66ab4b92 airtap: test android up to latest version 2019-08-06 18:31:11 -07:00
Feross Aboukhadijeh 4c264353b6 airtap: only test iphone 10.3+ (older was removed) 2019-08-06 18:30:52 -07:00
Feross Aboukhadijeh 5a834dcf16 airtap: Only test last 5 versions of chrome, firefox, edge 2019-08-06 18:30:38 -07:00
Feross Aboukhadijeh 7df5e4e076 airtap@2 2019-08-06 18:27:35 -07:00
Feross Aboukhadijeh 8346bacf94 ignore package-lock.json 2019-08-06 18:17:47 -07:00
Feross Aboukhadijeh 72bd014322 Merge pull request #103 from reggi/master
Add test folder to .npmignore
2019-08-06 18:16:12 -07:00
Thomas Reggi cb2aad2640 add yml files 2019-01-04 00:34:01 -05:00
Thomas Reggi 9d51d294ac ignore test 2019-01-04 00:32:09 -05:00
John Hiesey e60ce5fb99 Replace erroneous test disable 2018-10-02 21:45:10 -07:00
John Hiesey 9390b50f0d Bump readable-stream version again 2018-10-02 13:58:23 -07:00
John Hiesey 01e6e83bf9 Remove to-arraybuffer dependency 2018-10-02 10:32:58 -07:00
John Hiesey 00bed7dc11 Bump readable-stream version 2018-10-02 10:32:01 -07:00
John Hiesey 6bdba6c1ae Merge pull request #95 from hugomrdias/patch-1
Delete ie8-polyfill.js
2018-09-27 02:53:47 -07:00
Hugo Dias faeca6025b Delete ie8-polyfill.js 2018-09-27 10:52:01 +01:00
John Hiesey 00a4d3a5a8 Drop support for old Android browsers 2018-09-24 18:17:21 -07:00
John Hiesey 270011d074 Readme cleanup 2018-09-24 16:59:04 -07:00
John Hiesey 6f81d63645 Re-enable IE11 tests
Going to wait for the readable-stream fix before releasing
v3.0.0
2018-09-24 15:45:22 -07:00
John Hiesey bd3cd9b7ce Upgrade readable-stream to v3.0.3
This breaks IE11, but that should be fixed soon.
2018-09-24 15:05:14 -07:00
John Hiesey 4c2fd5a65d Re-disable android 7 tests 2018-09-24 14:39:04 -07:00
John Hiesey 0887fcf0b4 Major cleanup to remove IE10 and earlier support 2018-09-24 14:09:42 -07:00
John Hiesey 2a8467dd84 Merge pull request #93 from hugomrdias/fix/post
fix: fix >150mb bodies from crashing
2018-09-24 11:14:57 -07:00
Hugo Dias 983a99ca6c fix: fix >150mb bodies from crashing 2018-09-24 14:32:28 +01:00
John Hiesey 718f5127ec Update airtap 2018-08-22 22:46:23 -07:00
John Hiesey 65aed45b2d 2.8.3 2018-06-01 17:52:26 -07:00
John Hiesey 05dd964945 Merge pull request #89 from wmhilton/patch-1
Allow setting User-Agent Header
2018-06-01 17:33:29 -07:00
William Hilton 4f73bb1a3c Allow setting User-Agent Header
The User-Agent header has not been forbidden since Firefox 43 (see https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name).

> Note: The User-Agent header is no longer forbidden, as per spec — see forbidden header name list (this was implemented in Firefox 43) — it can now be set in a Fetch Headers object, or via XHR setRequestHeader().

I've had success setting it in Firefox and Edge for `fetch` and it should work for XMLHttpRequest as well but I'm too lazy to look up how to use XMLHttpRequest. I haven't had any luck setting User-Agent it in Chrome yet - may be a Chrome bug - but I'm not seeing any warnings in the terminal when I use it either, so I don't think allowing it will cause any spurious warnings.
2018-06-01 16:47:30 -04:00
John Hiesey 663f88323c 2.8.2 2018-05-09 19:26:31 -07:00
John Hiesey 12a0b3fd2a npm update 2018-05-09 16:37:22 -07:00
John Hiesey 520cc451e8 Clear fetch timeout after request finishes
Instead of right when response is created, which misses timeouts
that occur later
2018-05-08 21:52:39 -07:00
John Hiesey 5c3b919dab Fix edge tests 2018-05-08 21:52:05 -07:00
John Hiesey 5bc3a7205e Add (disabled) test for timeout after success
Unfortunately, reasonable timeout lengths tend to cause
spurious failures, so this test shouldn't be enabled
normally.
2018-05-08 20:37:36 -07:00
John Hiesey 80cbe3c5fe Improve fetch error handling 2018-05-08 17:36:01 -07:00
John Hiesey c3ab1f7bf0 Update package-lock.json 2018-05-08 16:18:22 -07:00
John Hiesey 98095e85eb Bump airtap version 2018-05-08 16:18:11 -07:00
John Hiesey 6547015c3d Also clear fetch timeout on error 2018-05-08 16:13:41 -07:00
John Hiesey 4b8abf52f3 Fetch clearTimeout fixup 2018-05-08 16:07:46 -07:00
John Hiesey 472ed03ea7 Merge pull request #87 from luozhang002/fetchmode
fix:add clearTimeout issue#85
2018-05-08 16:04:48 -07:00
罗章 16ec2ee996 fix:add clearTimeout 2018-05-03 13:24:32 +08:00
19 changed files with 179 additions and 6724 deletions
+15 -10
View File
@@ -1,23 +1,28 @@
sauce_connect: true
providers:
- airtap-sauce
browsers:
- name: chrome
version: 39..latest
version: -2..latest
- name: firefox
version: 34..latest
version: -2..latest
- name: safari
version: 8..latest
- name: microsoftedge
version: 13..latest
- name: MicrosoftEdge
version: -2..latest
- name: ie
version: 9..latest
version: 11
- name: iphone
version: '9.3..latest'
version: '10.3..latest'
- name: android
version: '4.4..6.0' # TODO: change this back to latest once https://github.com/airtap/browsers/issues/3 is fixed
version: '6.0..latest'
server: ./test/server/index.js
scripts:
- "/ie8-polyfill.js"
- "/test-polyfill.js"
browserify:
- options:
dedupe: false
dedupe: false
presets:
local:
providers: airtap-manual
browsers:
- name: manual
+2 -1
View File
@@ -1,5 +1,6 @@
.airtaprc
.DS_Store
bundle.js
node_modules
npm-debug.log
.airtaprc
package-lock.json
+3
View File
@@ -0,0 +1,3 @@
.airtap.yml
.travis.yml
test/
+12 -22
View File
@@ -22,23 +22,13 @@ has to be held in memory at once:
* Chrome >= 43 (using the `fetch` API)
* Firefox >= 9 (using `moz-chunked-arraybuffer` responseType with xhr)
The following browsers support pseudo-streaming, where the data is available before the
request finishes, but the entire response must be held in memory:
* Chrome
* Safari >= 5, and maybe older
* IE >= 10
* Most other Webkit-based browsers, including the default Android browser
All other supported browsers support pseudo-streaming, where the data is available before
the request finishes, but the entire response must be held in memory. This works for both
text and binary data.
All browsers newer than IE8 support binary responses. All of the above browsers that
support true streaming or pseudo-streaming support that for binary data as well
except for IE10. Old (presto-based) Opera also does not support binary streaming either.
### IE8 note:
As of version 2.0.0, IE8 support requires the user to supply polyfills for
`Object.keys`, `Array.prototype.forEach`, and `Array.prototype.indexOf`. Example
implementations are provided in [ie8-polyfill.js](ie8-polyfill.js); alternately,
you may want to consider using [es5-shim](https://github.com/es-shims/es5-shim).
All browsers with full ES5 support shouldn't require any polyfills.
### IE note:
As of version 3.0.0, IE10 and below are no longer supported. IE11 support will remain for
now.
## How do you use it?
@@ -75,7 +65,7 @@ at the expense of causing the 'content-type' response header to be incorrectly r
(as 'text/plain; charset=x-user-defined') in some browsers, notably Safari and Chrome 42
and older. Preserves binary data whenever possible. In some cases the implementation may
also be a bit slow. This was the default in versions of this module before 1.5.
* 'prefer-stream': Provide data before the request completes even if binary data (anything
* 'prefer-streaming': Provide data before the request completes even if binary data (anything
that isn't a single-byte ASCII or UTF8 character) will be corrupted. Of course, this option
is only safe for text data. May also cause the 'content-type' response header to be
incorrectly reported (as 'text/plain; charset=x-user-defined').
@@ -94,7 +84,7 @@ option, which applies to opening the connection.
* `http.Agent` is only a stub
* The 'socket', 'connect', 'upgrade', and 'continue' events on `http.ClientRequest`.
* Any operations, including `request.setTimeout`, that operate directly on the underlying
* Any operations, other than `request.setTimeout`, that operate directly on the underlying
socket.
* Any options that are disallowed for security reasons. This includes setting or getting
certain headers.
@@ -104,8 +94,6 @@ the server.
* `message.trailers` and `message.rawTrailers` will remain empty.
* Redirects are followed silently by the browser, so it isn't possible to access the 301/302
redirect pages.
* The `timeout` event/option and `setTimeout` functions, which operate on the underlying
socket, are not available. However, see `options.requestTimeout` above.
## Example
@@ -132,12 +120,14 @@ that run in the browser (found in `test/browser`). Normally the browser tests ru
Running `npm test` will run both sets of tests, but in order for the Sauce Labs tests to run
you will need to sign up for an account (free for open source projects) and put the
credentials in a [`.zuulrc` file](https://github.com/defunctzombie/zuul/wiki/zuulrc).
credentials in a [`.airtaprc` file](https://github.com/airtap/airtap/blob/master/doc/airtaprc.md).
You will also need to run a [Sauce Connect Proxy](https://wiki.saucelabs.com/display/DOCS/Sauce+Connect+Proxy)
with the same credentials.
To run just the Node tests, run `npm run test-node`.
To run the browser tests locally, run `npm run test-browser-local` and point your browser to
`http://localhost:8080/__zuul`
the link shown in your terminal.
## License
-168
View File
@@ -1,168 +0,0 @@
// These polyfills taken from MDN (developer.mozilla.org)
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function() {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function(obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.14
// Reference: http://es5.github.io/#x15.4.4.14
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(searchElement, fromIndex) {
var k;
// 1. Let O be the result of calling ToObject passing
// the this value as the argument.
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var O = Object(this);
// 2. Let lenValue be the result of calling the Get
// internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If len is 0, return -1.
if (len === 0) {
return -1;
}
// 5. If argument fromIndex was passed let n be
// ToInteger(fromIndex); else let n be 0.
var n = +fromIndex || 0;
if (Math.abs(n) === Infinity) {
n = 0;
}
// 6. If n >= len, return -1.
if (n >= len) {
return -1;
}
// 7. If n >= 0, then Let k be n.
// 8. Else, n<0, Let k be len - abs(n).
// If k is less than 0, then let k be 0.
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 9. Repeat, while k < len
while (k < len) {
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the
// HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
// i. Let elementK be the result of calling the Get
// internal method of O with the argument ToString(k).
// ii. Let same be the result of applying the
// Strict Equality Comparison Algorithm to
// searchElement and elementK.
// iii. If same is true, return k.
if (k in O && O[k] === searchElement) {
return k;
}
k++;
}
return -1;
};
}
+3 -17
View File
@@ -4,12 +4,6 @@ exports.writableStream = isFunction(global.WritableStream)
exports.abortController = isFunction(global.AbortController)
exports.blobConstructor = false
try {
new Blob([new ArrayBuffer(1)])
exports.blobConstructor = true
} catch (e) {}
// The xhr request to example.com may violate some restrictive CSP configurations,
// so if we're running in a browser that supports `fetch`, avoid calling getXHR()
// and assume support for certain features below.
@@ -45,27 +39,19 @@ function checkTypeSupport (type) {
return false
}
// For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'.
// Safari 7.1 appears to have fixed this bug.
var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined'
var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice)
// If fetch is supported, then arraybuffer will be supported too. Skip calling
// checkTypeSupport(), since that calls getXHR().
exports.arraybuffer = exports.fetch || (haveArrayBuffer && checkTypeSupport('arraybuffer'))
exports.arraybuffer = exports.fetch || checkTypeSupport('arraybuffer')
// These next two tests unavoidably show warnings in Chrome. Since fetch will always
// be used if it's available, just return false for these to avoid the warnings.
exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream')
exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer &&
checkTypeSupport('moz-chunked-arraybuffer')
exports.msstream = !exports.fetch && checkTypeSupport('ms-stream')
exports.mozchunkedarraybuffer = !exports.fetch && checkTypeSupport('moz-chunked-arraybuffer')
// If fetch is supported, then overrideMimeType will be supported too. Skip calling
// getXHR().
exports.overrideMimeType = exports.fetch || (getXHR() ? isFunction(getXHR().overrideMimeType) : false)
exports.vbArray = isFunction(global.VBArray)
function isFunction (value) {
return typeof value === 'function'
}
+54 -25
View File
@@ -2,7 +2,6 @@ var capability = require('./capability')
var inherits = require('inherits')
var response = require('./response')
var stream = require('readable-stream')
var toArrayBuffer = require('to-arraybuffer')
var IncomingMessage = response.IncomingMessage
var rStates = response.readyStates
@@ -16,8 +15,6 @@ function decideMode (preferBinary, useFetch) {
return 'ms-stream'
} else if (capability.arraybuffer && preferBinary) {
return 'arraybuffer'
} else if (capability.vbArray && preferBinary) {
return 'text:vbarray'
} else {
return 'text'
}
@@ -31,7 +28,7 @@ var ClientRequest = module.exports = function (opts) {
self._body = []
self._headers = {}
if (opts.auth)
self.setHeader('Authorization', 'Basic ' + new Buffer(opts.auth).toString('base64'))
self.setHeader('Authorization', 'Basic ' + Buffer.from(opts.auth).toString('base64'))
Object.keys(opts.headers).forEach(function (name) {
self.setHeader(name, opts.headers[name])
})
@@ -56,6 +53,9 @@ var ClientRequest = module.exports = function (opts) {
throw new Error('Invalid value for opts.mode')
}
self._mode = decideMode(preferBinary, useFetch)
self._fetchTimer = null
self._socketTimeout = null
self._socketTimer = null
self.on('finish', function () {
self._onFinish()
@@ -98,22 +98,17 @@ ClientRequest.prototype._onFinish = function () {
return
var opts = self._opts
if ('timeout' in opts && opts.timeout !== 0) {
self.setTimeout(opts.timeout)
}
var headersObj = self._headers
var body = null
if (opts.method !== 'GET' && opts.method !== 'HEAD') {
if (capability.arraybuffer) {
body = toArrayBuffer(Buffer.concat(self._body))
} else if (capability.blobConstructor) {
body = new global.Blob(self._body.map(function (buffer) {
return toArrayBuffer(buffer)
}), {
type: (headersObj['content-type'] || {}).value || ''
})
} else {
// get utf8 string
body = Buffer.concat(self._body).toString()
}
}
body = new Blob(self._body, {
type: (headersObj['content-type'] || {}).value || ''
});
}
// create flattened list of headers
var headersList = []
@@ -137,7 +132,7 @@ ClientRequest.prototype._onFinish = function () {
self._fetchAbortController = controller
if ('requestTimeout' in opts && opts.requestTimeout !== 0) {
global.setTimeout(function () {
self._fetchTimer = global.setTimeout(function () {
self.emit('requestTimeout')
if (self._fetchAbortController)
self._fetchAbortController.abort()
@@ -154,9 +149,12 @@ ClientRequest.prototype._onFinish = function () {
signal: signal
}).then(function (response) {
self._fetchResponse = response
self._resetTimers(false)
self._connect()
}, function (reason) {
self.emit('error', reason)
self._resetTimers(true)
if (!self._destroyed)
self.emit('error', reason)
})
} else {
var xhr = self._xhr = new global.XMLHttpRequest()
@@ -171,7 +169,7 @@ ClientRequest.prototype._onFinish = function () {
// Can't set responseType on really old browsers
if ('responseType' in xhr)
xhr.responseType = self._mode.split(':')[0]
xhr.responseType = self._mode
if ('withCredentials' in xhr)
xhr.withCredentials = !!opts.withCredentials
@@ -210,6 +208,7 @@ ClientRequest.prototype._onFinish = function () {
xhr.onerror = function () {
if (self._destroyed)
return
self._resetTimers(true)
self.emit('error', new Error('XHR error'))
}
@@ -241,13 +240,15 @@ function statusValid (xhr) {
ClientRequest.prototype._onXHRProgress = function () {
var self = this
self._resetTimers(false)
if (!statusValid(self._xhr) || self._destroyed)
return
if (!self._response)
self._connect()
self._response._onXHRProgress()
self._response._onXHRProgress(self._resetTimers.bind(self))
}
ClientRequest.prototype._connect = function () {
@@ -256,7 +257,7 @@ ClientRequest.prototype._connect = function () {
if (self._destroyed)
return
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode)
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode, self._resetTimers.bind(self))
self._response.on('error', function(err) {
self.emit('error', err)
})
@@ -271,15 +272,35 @@ ClientRequest.prototype._write = function (chunk, encoding, cb) {
cb()
}
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () {
ClientRequest.prototype._resetTimers = function (done) {
var self = this
global.clearTimeout(self._socketTimer)
self._socketTimer = null
if (done) {
global.clearTimeout(self._fetchTimer)
self._fetchTimer = null
} else if (self._socketTimeout) {
self._socketTimer = global.setTimeout(function () {
self.emit('timeout')
}, self._socketTimeout)
}
}
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function (err) {
var self = this
self._destroyed = true
self._resetTimers(true)
if (self._response)
self._response._destroyed = true
if (self._xhr)
self._xhr.abort()
else if (self._fetchAbortController)
self._fetchAbortController.abort()
if (err)
self.emit('error', err)
}
ClientRequest.prototype.end = function (data, encoding, cb) {
@@ -292,8 +313,17 @@ ClientRequest.prototype.end = function (data, encoding, cb) {
stream.Writable.prototype.end.call(self, data, encoding, cb)
}
ClientRequest.prototype.setTimeout = function (timeout, cb) {
var self = this
if (cb)
self.once('timeout', cb)
self._socketTimeout = timeout
self._resetTimers(false)
}
ClientRequest.prototype.flushHeaders = function () {}
ClientRequest.prototype.setTimeout = function () {}
ClientRequest.prototype.setNoDelay = function () {}
ClientRequest.prototype.setSocketKeepAlive = function () {}
@@ -318,6 +348,5 @@ var unsafeHeaders = [
'trailer',
'transfer-encoding',
'upgrade',
'user-agent',
'via'
]
+22 -29
View File
@@ -10,7 +10,7 @@ var rStates = exports.readyStates = {
DONE: 4
}
var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode, resetTimers) {
var self = this
stream.Readable.call(self)
@@ -43,10 +43,11 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
if (capability.writableStream) {
var writable = new WritableStream({
write: function (chunk) {
resetTimers(false)
return new Promise(function (resolve, reject) {
if (self._destroyed) {
return
} else if(self.push(new Buffer(chunk))) {
reject()
} else if(self.push(Buffer.from(chunk))) {
resolve()
} else {
self._resumeFetch = resolve
@@ -54,6 +55,7 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
})
},
close: function () {
resetTimers(true)
if (!self._destroyed)
self.push(null)
},
@@ -64,7 +66,11 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
})
try {
response.body.pipeTo(writable)
response.body.pipeTo(writable).catch(function (err) {
resetTimers(true)
if (!self._destroyed)
self.emit('error', err)
})
return
} catch (e) {} // pipeTo method isn't defined. Can't find a better way to feature test this
}
@@ -74,13 +80,15 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
reader.read().then(function (result) {
if (self._destroyed)
return
resetTimers(result.done)
if (result.done) {
self.push(null)
return
}
self.push(new Buffer(result.value))
self.push(Buffer.from(result.value))
read()
}).catch(function(err) {
}).catch(function (err) {
resetTimers(true)
if (!self._destroyed)
self.emit('error', err)
})
@@ -139,36 +147,19 @@ IncomingMessage.prototype._read = function () {
}
}
IncomingMessage.prototype._onXHRProgress = function () {
IncomingMessage.prototype._onXHRProgress = function (resetTimers) {
var self = this
var xhr = self._xhr
var response = null
switch (self._mode) {
case 'text:vbarray': // For IE9
if (xhr.readyState !== rStates.DONE)
break
try {
// This fails in IE8
response = new global.VBArray(xhr.responseBody).toArray()
} catch (e) {}
if (response !== null) {
self.push(new Buffer(response))
break
}
// Falls through in IE8
case 'text':
try { // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4
response = xhr.responseText
} catch (e) {
self._mode = 'text:vbarray'
break
}
response = xhr.responseText
if (response.length > self._pos) {
var newData = response.substr(self._pos)
if (self._charset === 'x-user-defined') {
var buffer = new Buffer(newData.length)
var buffer = Buffer.alloc(newData.length)
for (var i = 0; i < newData.length; i++)
buffer[i] = newData.charCodeAt(i) & 0xff
@@ -183,13 +174,13 @@ IncomingMessage.prototype._onXHRProgress = function () {
if (xhr.readyState !== rStates.DONE || !xhr.response)
break
response = xhr.response
self.push(new Buffer(new Uint8Array(response)))
self.push(Buffer.from(new Uint8Array(response)))
break
case 'moz-chunked-arraybuffer': // take whole
response = xhr.response
if (xhr.readyState !== rStates.LOADING || !response)
break
self.push(new Buffer(new Uint8Array(response)))
self.push(Buffer.from(new Uint8Array(response)))
break
case 'ms-stream':
response = xhr.response
@@ -198,11 +189,12 @@ IncomingMessage.prototype._onXHRProgress = function () {
var reader = new global.MSStreamReader()
reader.onprogress = function () {
if (reader.result.byteLength > self._pos) {
self.push(new Buffer(new Uint8Array(reader.result.slice(self._pos))))
self.push(Buffer.from(new Uint8Array(reader.result.slice(self._pos))))
self._pos = reader.result.byteLength
}
}
reader.onload = function () {
resetTimers(true)
self.push(null)
}
// reader.onerror = ??? // TODO: this
@@ -212,6 +204,7 @@ IncomingMessage.prototype._onXHRProgress = function () {
// The ms-stream case handles end separately in reader.onload()
if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') {
resetTimers(true)
self.push(null)
}
}
-6369
View File
File diff suppressed because it is too large Load Diff
+15 -14
View File
@@ -1,6 +1,6 @@
{
"name": "stream-http",
"version": "2.8.1",
"version": "3.1.1",
"description": "Streaming http in the browser",
"main": "index.js",
"repository": {
@@ -10,8 +10,8 @@
"scripts": {
"test": "npm run test-node && ([ -n \"${TRAVIS_PULL_REQUEST}\" -a \"${TRAVIS_PULL_REQUEST}\" != 'false' ] || npm run test-browser)",
"test-node": "tape test/node/*.js",
"test-browser": "airtap --loopback airtap.local -- test/browser/*.js",
"test-browser-local": "airtap --no-instrument --local 8080 -- test/browser/*.js"
"test-browser": "airtap --concurrency 1 -- test/browser/*.js",
"test-browser-local": "airtap --preset local -- test/browser/*.js"
},
"author": "John Hiesey",
"license": "MIT",
@@ -28,19 +28,20 @@
],
"dependencies": {
"builtin-status-codes": "^3.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.3.3",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
"inherits": "^2.0.4",
"readable-stream": "^3.6.0",
"xtend": "^4.0.2"
},
"devDependencies": {
"airtap": "^0.0.3",
"basic-auth": "^2.0.0",
"brfs": "^1.4.0",
"cookie-parser": "^1.4.3",
"express": "^4.16.2",
"tape": "^4.8.0",
"ua-parser-js": "^0.7.17",
"airtap": "^4.0.3",
"airtap-manual": "^1.0.0",
"airtap-sauce": "^1.1.0",
"basic-auth": "^2.0.1",
"brfs": "^2.0.2",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"tape": "^5.2.2",
"ua-parser-js": "^0.7.28",
"webworkify": "^1.5.0"
}
}
+4 -25
View File
@@ -5,18 +5,7 @@ var UAParser = require('ua-parser-js')
var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Binary streaming doesn't work in IE10 or below
var skipStreamingCheck = (browserName === 'IE' && browserVersion <= 10)
// Binary data gets corrupted in IE8 or below
var skipVerification = (browserName === 'IE' && browserVersion <= 8)
// IE8 tends to throw up modal dialogs complaining about scripts running too long
// Since streaming doesn't actually work there anyway, just use one copy
var COPIES = skipVerification ? 1 : 20
var COPIES = 20
var MIN_PIECES = 2
var referenceOnce = fs.readFileSync(__dirname + '/../server/static/browserify.png')
@@ -32,15 +21,8 @@ test('binary streaming', function (t) {
}, function (res) {
var buffers = []
res.on('end', function () {
if (skipVerification)
t.skip('binary data not preserved on IE <= 8')
else
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
if (skipStreamingCheck)
t.skip('streaming not available on IE <= 8')
else
t.ok(buffers.length >= MIN_PIECES, 'received in multiple parts')
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.ok(buffers.length >= MIN_PIECES, 'received in multiple parts')
t.end()
})
@@ -57,10 +39,7 @@ test('large binary request without streaming', function (t) {
}, function (res) {
var buffers = []
res.on('end', function () {
if (skipVerification)
t.skip('binary data not preserved on IE <= 8')
else
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.end()
})
+1 -10
View File
@@ -5,12 +5,6 @@ var UAParser = require('ua-parser-js')
var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Binary data gets corrupted in IE8 or below
var skipVerification = (browserName === 'IE' && browserVersion <= 8)
var reference = fs.readFileSync(__dirname + '/../server/static/browserify.png')
test('binary download', function (t) {
@@ -18,10 +12,7 @@ test('binary download', function (t) {
var buffers = []
res.on('end', function () {
if (skipVerification)
t.skip('binary data not preserved on IE <= 8')
else
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.end()
})
+1 -13
View File
@@ -5,15 +5,6 @@ var UAParser = require('ua-parser-js')
var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Binary request bodies don't work in a bunch of browsers
var skipVerification = ((browserName === 'IE' && browserVersion <= 10) ||
(browserName === 'Safari' && browserVersion <= 5) ||
(browserName === 'WebKit' && browserVersion <= 534) || // Old mobile safari
(browserName === 'Android Browser' && browserVersion <= 4))
var reference = fs.readFileSync(__dirname + '/../server/static/browserify.png')
test('post binary', function (t) {
@@ -24,10 +15,7 @@ test('post binary', function (t) {
var buffers = []
res.on('end', function () {
if (skipVerification)
t.skip('binary data not preserved on this browser')
else
t.ok(reference.equals(Buffer.concat(buffers)), 'echoed contents match')
t.ok(reference.equals(Buffer.concat(buffers)), 'echoed contents match')
t.end()
})
+1 -4
View File
@@ -28,10 +28,7 @@ test('text streaming', function (t) {
var buffers = []
res.on('end', function () {
if (skipStreamingCheck)
t.skip('streaming not available on IE <= 8')
else
t.ok(buffers.length >= MIN_PIECES, 'received in multiple parts')
t.ok(buffers.length >= MIN_PIECES, 'received in multiple parts')
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.end()
})
-1
View File
@@ -15,7 +15,6 @@ var skipResponseUrl = ((browserName === 'IE') ||
(browserName === 'Chrome' && browserVersion <= 36) ||
(browserName === 'Firefox' && browserVersion <= 31) ||
((browserName === 'Safari' || browserName === 'Mobile Safari') && browserVersion <= 8) ||
(browserName === 'WebKit') || // Old mobile safari
(browserName === 'Android Browser' && browserVersion <= 4))
var reference = fs.readFileSync(__dirname + '/../server/static/basic.txt')
+43 -2
View File
@@ -4,7 +4,7 @@ var test = require('tape')
var http = require('../..')
test('timeout', function (t) {
test('requestTimeout', function (t) {
var req = http.get({
path: '/browserify.png?copies=5',
requestTimeout: 10 // ms
@@ -16,7 +16,48 @@ test('timeout', function (t) {
})
})
req.on('requestTimeout', function () {
t.pass('got timeout')
t.pass('got requestTimeout')
t.end()
})
})
// TODO: reenable this if there's a way to make it simultaneously
// fast and reliable
test.skip('no requestTimeout after success', function (t) {
var req = http.get({
path: '/basic.txt',
requestTimeout: 50000 // ms
}, function (res) {
res.on('data', function (data) {
})
res.on('end', function () {
t.pass('success')
global.setTimeout(function () {
t.end()
}, 50000)
})
})
req.on('requestTimeout', function () {
t.fail('unexpected requestTimeout')
})
})
test('setTimeout', function (t) {
t.plan(2)
var req = http.get({
path: '/browserify.png?copies=5'
}, function (res) {
res.on('data', function (data) {
})
res.on('end', function () {
t.fail('request completed (should have timed out)')
})
})
req.setTimeout(10, function () {
t.pass('got setTimeout callback')
})
req.on('timeout', function () {
t.pass('got timeout')
})
})
+2 -12
View File
@@ -4,20 +4,10 @@ var UAParser = require('ua-parser-js')
var url = require('url')
var work = require('webworkify')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Skip browsers with poor or nonexistant WebWorker support
var skip = ((browserName === 'IE' && browserVersion <= 10) ||
(browserName === 'Safari' && browserVersion <= 5) ||
(browserName === 'WebKit' && browserVersion <= 534) || // Old mobile safari
(browserName === 'Android Browser' && browserVersion <= 4))
var reference = fs.readFileSync(__dirname + '/../server/static/browserify.png')
test('binary download in WebWorker', {
skip: skip
}, function (t) {
// Temporarily disabled due to https://github.com/browserify/webworkify/issues/41
test.skip('binary download in WebWorker', function (t) {
// We have to use a global url, since webworkify puts the worker in a Blob,
// which doesn't have a proper location
var testUrl = url.resolve(global.location.href, '/browserify.png')
+1 -1
View File
@@ -132,6 +132,6 @@ app.use(function (req, res, next) {
app.use(express.static(path.join(__dirname, 'static')))
var port = parseInt(process.env.AIRTAP_PORT) || 8199
var port = parseInt(process.env.AIRTAP_SUPPORT_PORT) || 8199
console.log('Test server listening on port', port)
server.listen(port)
-1
View File
@@ -1 +0,0 @@
../../../ie8-polyfill.js