Compare commits

...

103 Commits

Author SHA1 Message Date
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
John Hiesey 8cf284cd4b 2.8.1 2018-03-14 13:27:52 -07:00
John Hiesey 709d1acc3d Stop trying to run tests on iOS 8
It seems that this is no longer supported by Sauce Labs
2018-03-14 13:14:14 -07:00
John Hiesey f800fad249 Fix incorrect definition of http.IncomingMessage
Also add test for top-level http properties, plus a stub http.globalAgent
Fixes #81
2018-03-14 13:08:47 -07:00
John Hiesey 920dd3cd48 Bump airtap version 2018-02-26 22:50:33 -08:00
John Hiesey 433d1d5e46 Stop testing safari 7 since sauce labs gives errors 2018-02-26 22:50:01 -08:00
John Hiesey 86bfe01159 Re-enable webworker test with workaround 2018-02-26 17:43:26 -08:00
John Hiesey 8188419852 Merge pull request #84 from jhiesey/airtap
Switch from zuul to airtap for running browser tests
2018-02-22 00:56:32 -08:00
John Hiesey aa4882c7c6 Fix running browser tests locally with airtap 2018-02-22 00:40:33 -08:00
John Hiesey d62864934a Disable android 7 tests due to airtap issue
Upstream issue: https://github.com/airtap/browsers/issues/3
2018-02-22 00:29:58 -08:00
John Hiesey e875fc72b0 Switch from zuul to airtap for tests 2018-02-21 22:22:04 -08:00
John Hiesey 38ffb38660 2.8.0 2018-01-15 02:48:35 -08:00
John Hiesey 16c1baf178 Add Uint8Array support for body
This will be used if available. Fixes #57 and #80
2018-01-15 01:16:31 -08:00
John Hiesey 0ecf194fa4 Remove test support for older browsers
Opera (all versions) and Safari < 7 aren't supported by sauce labs
anymore, so don't test them.
2018-01-15 01:16:31 -08:00
John Hiesey d4631b211c Change timeout behavior
Add opts.requestTimeout. Fixes #66
2018-01-15 01:16:31 -08:00
John Hiesey bf580d32dd Expose ClientRequest and IncomingMessage constructors
For compatibility with node. Fixes #76 and #81.
2018-01-15 01:16:31 -08:00
John Hiesey 80f74c2107 Update dependencies and add npm-shrinkwrap.json 2018-01-15 01:16:31 -08:00
John Hiesey c2e1444670 Update documentation 2018-01-15 01:03:26 -08:00
John Hiesey 4fefc64d39 Don't emit error after destroyed 2018-01-15 01:03:26 -08:00
John Hiesey f94670b6b4 Add proper abort/timeout support for fetch
Fixes #26, finally!
2018-01-15 01:03:26 -08:00
John Hiesey 46c35150fc Implement backpressure
Uses WritableStream, which is still quite new.
2018-01-15 01:03:07 -08:00
John Hiesey c09a871543 2.7.2 2017-06-12 13:21:48 -07:00
John Hiesey 856a572341 fix tests on Safari 10.0 on iOS 10.3 2017-06-12 13:01:14 -07:00
John Hiesey 4175a65117 Merge pull request #78 from EsrefDurna/master
updated package.json
2017-06-12 11:51:51 -07:00
Esref Durna e2bfae151c updated package cookie-parser from 1.3.5 to 1.4.3
Npm link :  https://www.npmjs.com/package/cookie-parser
 Repository link : https://github.com/expressjs/cookie-parser/releases
2017-06-12 01:24:11 +00:00
John Hiesey 8eab4b3e5f 2.7.1 2017-05-08 17:44:33 -07:00
John Hiesey 46923f37d9 Fix Android tests
Not sure how this ever worked. This seems to have been broken for quite a while.
2017-05-08 17:31:38 -07:00
John Hiesey 2771d95bde Merge pull request #77 from GusCaplan/patch-1
fix getHeader when header isn't available
2017-04-28 18:34:51 -07:00
Gus Caplan 7c2e61fac0 fix getHeader when header isn't available 2017-04-26 02:05:49 -05:00
John Hiesey 1dc9ea32f5 2.7.0 2017-04-03 23:46:27 -07:00
John Hiesey e8ed108767 Sauce labs no longer supports tests on android < 4.4 2017-04-03 23:45:47 -07:00
John Hiesey 4cf6771177 Disable broken timeout test
timeout support is fairly broken; see #66
2017-04-03 23:43:08 -07:00
John Hiesey e54de15542 Handle arrays in request headers and improve header handling
Passing an array as a header value now works as in node.
Header handling with multiple values for the same header is also
tested, and mime type test updated for safari 10.1

Fixes #73
2017-04-03 22:25:57 -07:00
John Hiesey 943f5bc89d use blacklist instead of whitelist for methods with bodies
Instead of only permitting bodies on certain methods, only
prohibit them when the browser would give an error (with fetch)
or ignore them (with XHR). This allows bodies with custom
methods and is closer to the behavior of http in node.

Fixes #69
2017-04-03 20:25:20 -07:00
John Hiesey 1c25d6f3a3 bump dependency versions 2017-04-03 20:20:47 -07:00
John Hiesey b63537f11d 2.6.3 2017-01-19 03:26:43 -08:00
John Hiesey 11d14fc642 Revert unnecessary part of previous change 2017-01-17 20:23:25 -08:00
John Hiesey 8e1f534a8a Fix Edge fetch errors 2017-01-17 18:39:22 -08:00
John Hiesey c1417c5dfa 2.6.2 2017-01-16 02:00:08 -08:00
John Hiesey 8df10e0d65 Avoid passing undefined to xhr.send()
Provides a more elegant fix to #67
2017-01-16 01:57:32 -08:00
John Hiesey 5ee30ad5cc Fix timeout test failure 2017-01-16 00:35:53 -08:00
John Hiesey 9321e56abd 2.6.1 2017-01-11 23:44:27 -08:00
John Hiesey 881e7c8f3d Merge pull request #65 from jhiesey/csp-xhr-fix
Avoid xhr request to example.com if fetch is supported
2017-01-11 22:44:35 -08:00
Feross Aboukhadijeh 43761f2799 Avoid xhr request to example.com if fetch is supported
For: https://github.com/brave/browser-laptop/issues/5981
2017-01-10 22:17:09 -08:00
John Hiesey 70f8c7d0b7 2.6.0 2017-01-06 01:58:52 -10:00
John Hiesey f304ef13a2 bump builtin-status-codes version 2017-01-06 01:24:15 -10:00
John Hiesey e8ef98b286 style consistency 2017-01-06 01:04:07 -10:00
John Hiesey 3af33f862f Merge pull request #61 from dominictarr/master
if xhr.open throws, then no xhr is allowed
2017-01-06 03:00:46 -08:00
John Hiesey 138d6c1d29 Merge pull request #62 from rlisagor/master
Catching fetch `read()` errors
2017-01-06 02:57:53 -08:00
Roman Lisagor f97dd885ea Catching fetch read() errors
Errors that occur while reading from the ReadableStream that is returned as part of a `fetch` request were not handled. This change propagates these errors up to the `ClientRequest`.
2017-01-04 14:41:01 -08:00
John Hiesey f9fb1c724c Merge pull request #55 from node-influx/master
Support timeout option in http.request
2016-12-27 13:44:03 -08:00
Dominic Tarr 1b077bf249 if xhr.open throws, then no xhr is allowed 2016-12-09 21:04:31 +01:00
John Hiesey e342cdbb10 Merge pull request #59 from mikeal/service-worker
Adding support for Service Workers.
2016-11-16 19:22:00 -08:00
Mikeal Rogers 0a04a09f68 Adding support for Service Workers. 2016-11-16 19:18:19 -08:00
Connor Peet 57d0ab245f Support timeout option in http.request 2016-10-17 19:17:44 -07:00
24 changed files with 406 additions and 390 deletions
+22
View File
@@ -0,0 +1,22 @@
sauce_connect: true
browsers:
- name: chrome
version: -2..latest
- name: firefox
version: -2..latest
- name: safari
version: 8..latest
- name: MicrosoftEdge
version: -2..latest
- name: ie
version: 11
- name: iphone
version: '10.3..latest'
- name: android
version: '6.0..latest'
server: ./test/server/index.js
scripts:
- "/test-polyfill.js"
browserify:
- options:
dedupe: false
+2 -1
View File
@@ -1,5 +1,6 @@
.airtaprc
.DS_Store
bundle.js
node_modules
npm-debug.log
.zuulrc
package-lock.json
+3
View File
@@ -0,0 +1,3 @@
.airtap.yml
.travis.yml
test/
+5 -1
View File
@@ -1,3 +1,7 @@
language: node_js
node_js:
- "6.4"
- "node"
addons:
sauce_connect: true
hosts:
- airtap.local
-22
View File
@@ -1,22 +0,0 @@
ui: tape
browsers:
- name: chrome
version: 39..latest
- name: firefox
version: 34..latest
- name: safari
version: 5..latest
- name: microsoftedge
version: 13..latest
- name: ie
version: 9..latest
- name: opera
version: 11..latest
- name: iphone
version: '8.1..latest'
- name: android
version: '4.0..latest'
server: ./test/server/index.js
scripts:
- "/ie8-polyfill.js"
- "/test-polyfill.js"
+25 -21
View File
@@ -13,28 +13,22 @@ This is heavily inspired by, and intended to replace, [http-browserify](https://
In accordance with its name, `stream-http` tries to provide data to its caller before
the request has completed whenever possible.
Backpressure, allowing the browser to only pull data from the server as fast as it is
consumed, is supported in:
* Chrome >= 58 (using `fetch` and `WritableStream`)
The following browsers support true streaming, where only a small amount of the request
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?
@@ -71,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').
@@ -80,6 +74,12 @@ capability. Preserves the correctness of binary data and the 'content-type' resp
* 'prefer-fast': Deprecated; now a synonym for 'default', which has the same performance
characteristics as this mode did in versions before 1.5.
* `options.requestTimeout` allows setting a timeout in millisecionds for XHR and fetch (if
supported by the browser). This is a limit on how long the entire process takes from
beginning to end. Note that this is not the same as the node `setTimeout` functions,
which apply to pauses in data transfer over the underlying socket, or the node `timeout`
option, which applies to opening the connection.
### Features missing compared to Node
* `http.Agent` is only a stub
@@ -94,6 +94,8 @@ 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
@@ -101,11 +103,11 @@ redirect pages.
http.get('/bundle.js', function (res) {
var div = document.getElementById('result');
div.innerHTML += 'GET /beep<br>';
res.on('data', function (buf) {
div.innerHTML += buf;
});
res.on('end', function () {
div.innerHTML += '<br>__END__';
});
@@ -120,12 +122,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;
};
}
+6
View File
@@ -1,4 +1,5 @@
var ClientRequest = require('./lib/request')
var response = require('./lib/response')
var extend = require('xtend')
var statusCodes = require('builtin-status-codes')
var url = require('url')
@@ -44,9 +45,14 @@ http.get = function get (opts, cb) {
return req
}
http.ClientRequest = ClientRequest
http.IncomingMessage = response.IncomingMessage
http.Agent = function () {}
http.Agent.defaultMaxSockets = 4
http.globalAgent = new http.Agent()
http.STATUS_CODES = statusCodes
http.METHODS = [
+39 -20
View File
@@ -1,17 +1,37 @@
exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)
exports.blobConstructor = false
try {
new Blob([new ArrayBuffer(1)])
exports.blobConstructor = true
} catch (e) {}
exports.writableStream = isFunction(global.WritableStream)
var xhr = new global.XMLHttpRequest()
// If XDomainRequest is available (ie only, where xhr might not work
// cross domain), use the page location. Otherwise use example.com
xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')
exports.abortController = isFunction(global.AbortController)
// 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.
var xhr
function getXHR () {
// Cache the xhr value
if (xhr !== undefined) return xhr
if (global.XMLHttpRequest) {
xhr = new global.XMLHttpRequest()
// If XDomainRequest is available (ie only, where xhr might not work
// cross domain), use the page location. Otherwise use example.com
// Note: this doesn't actually make an http request.
try {
xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')
} catch(e) {
xhr = null
}
} else {
// Service workers don't have XHR
xhr = null
}
return xhr
}
function checkTypeSupport (type) {
var xhr = getXHR()
if (!xhr) return false
try {
xhr.responseType = type
return xhr.responseType === type
@@ -19,22 +39,21 @@ 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 || checkTypeSupport('arraybuffer')
exports.arraybuffer = haveArrayBuffer && 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.overrideMimeType = isFunction(xhr.overrideMimeType)
exports.vbArray = isFunction(global.VBArray)
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)
function isFunction (value) {
return typeof value === 'function'
return typeof value === 'function'
}
xhr = null // Help gc
+64 -32
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,15 +28,15 @@ 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])
})
var preferBinary
var useFetch = true
if (opts.mode === 'disable-fetch') {
// If the use of XHR should be preferred and includes preserving the 'content-type' header
if (opts.mode === 'disable-fetch' || ('requestTimeout' in opts && !capability.abortController)) {
// If the use of XHR should be preferred. Not typically needed.
useFetch = false
preferBinary = true
} else if (opts.mode === 'prefer-streaming') {
@@ -56,6 +53,7 @@ var ClientRequest = module.exports = function (opts) {
throw new Error('Invalid value for opts.mode')
}
self._mode = decideMode(preferBinary, useFetch)
self._fetchTimer = null
self.on('finish', function () {
self._onFinish()
@@ -80,8 +78,10 @@ ClientRequest.prototype.setHeader = function (name, value) {
}
ClientRequest.prototype.getHeader = function (name) {
var self = this
return self._headers[name.toLowerCase()].value
var header = this._headers[name.toLowerCase()]
if (header)
return header.value
return null
}
ClientRequest.prototype.removeHeader = function (name) {
@@ -97,36 +97,57 @@ ClientRequest.prototype._onFinish = function () {
var opts = self._opts
var headersObj = self._headers
var body
if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH' || opts.method === 'MERGE') {
if (capability.blobConstructor) {
body = new global.Blob(self._body.map(function (buffer) {
return toArrayBuffer(buffer)
}), {
type: (headersObj['content-type'] || {}).value || ''
var body = null
if (opts.method !== 'GET' && opts.method !== 'HEAD') {
body = new Blob(self._body, {
type: (headersObj['content-type'] || {}).value || ''
});
}
// create flattened list of headers
var headersList = []
Object.keys(headersObj).forEach(function (keyName) {
var name = headersObj[keyName].name
var value = headersObj[keyName].value
if (Array.isArray(value)) {
value.forEach(function (v) {
headersList.push([name, v])
})
} else {
// get utf8 string
body = Buffer.concat(self._body).toString()
headersList.push([name, value])
}
}
})
if (self._mode === 'fetch') {
var headers = Object.keys(headersObj).map(function (name) {
return [headersObj[name].name, headersObj[name].value]
})
var signal = null
if (capability.abortController) {
var controller = new AbortController()
signal = controller.signal
self._fetchAbortController = controller
if ('requestTimeout' in opts && opts.requestTimeout !== 0) {
self._fetchTimer = global.setTimeout(function () {
self.emit('requestTimeout')
if (self._fetchAbortController)
self._fetchAbortController.abort()
}, opts.requestTimeout)
}
}
global.fetch(self._opts.url, {
method: self._opts.method,
headers: headers,
body: body,
headers: headersList,
body: body || undefined,
mode: 'cors',
credentials: opts.withCredentials ? 'include' : 'same-origin'
credentials: opts.withCredentials ? 'include' : 'same-origin',
signal: signal
}).then(function (response) {
self._fetchResponse = response
self._connect()
}, function (reason) {
self.emit('error', reason)
global.clearTimeout(self._fetchTimer)
if (!self._destroyed)
self.emit('error', reason)
})
} else {
var xhr = self._xhr = new global.XMLHttpRequest()
@@ -141,7 +162,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
@@ -149,8 +170,15 @@ ClientRequest.prototype._onFinish = function () {
if (self._mode === 'text' && 'overrideMimeType' in xhr)
xhr.overrideMimeType('text/plain; charset=x-user-defined')
Object.keys(headersObj).forEach(function (name) {
xhr.setRequestHeader(headersObj[name].name, headersObj[name].value)
if ('requestTimeout' in opts) {
xhr.timeout = opts.requestTimeout
xhr.ontimeout = function () {
self.emit('requestTimeout')
}
}
headersList.forEach(function (header) {
xhr.setRequestHeader(header[0], header[1])
})
self._response = null
@@ -219,7 +247,11 @@ 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._fetchTimer)
self._response.on('error', function(err) {
self.emit('error', err)
})
self.emit('response', self._response)
}
@@ -233,12 +265,13 @@ ClientRequest.prototype._write = function (chunk, encoding, cb) {
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () {
var self = this
self._destroyed = true
global.clearTimeout(self._fetchTimer)
if (self._response)
self._response._destroyed = true
if (self._xhr)
self._xhr.abort()
// Currently, there isn't a way to truly abort a fetch.
// If you like bikeshedding, see https://github.com/whatwg/fetch/issues/27
else if (self._fetchAbortController)
self._fetchAbortController.abort()
}
ClientRequest.prototype.end = function (data, encoding, cb) {
@@ -277,6 +310,5 @@ var unsafeHeaders = [
'trailer',
'transfer-encoding',
'upgrade',
'user-agent',
'via'
]
+55 -28
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, fetchTimer) {
var self = this
stream.Readable.call(self)
@@ -35,28 +35,64 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
self.statusCode = response.status
self.statusMessage = response.statusText
response.headers.forEach(function(header, key){
response.headers.forEach(function (header, key){
self.headers[key.toLowerCase()] = header
self.rawHeaders.push(key, header)
})
if (capability.writableStream) {
var writable = new WritableStream({
write: function (chunk) {
return new Promise(function (resolve, reject) {
if (self._destroyed) {
reject()
} else if(self.push(Buffer.from(chunk))) {
resolve()
} else {
self._resumeFetch = resolve
}
})
},
close: function () {
global.clearTimeout(fetchTimer)
if (!self._destroyed)
self.push(null)
},
abort: function (err) {
if (!self._destroyed)
self.emit('error', err)
}
})
// TODO: this doesn't respect backpressure. Once WritableStream is available, this can be fixed
try {
response.body.pipeTo(writable).catch(function (err) {
global.clearTimeout(fetchTimer)
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
}
// fallback for when writableStream or pipeTo aren't available
var reader = response.body.getReader()
function read () {
reader.read().then(function (result) {
if (self._destroyed)
return
if (result.done) {
global.clearTimeout(fetchTimer)
self.push(null)
return
}
self.push(new Buffer(result.value))
self.push(Buffer.from(result.value))
read()
}).catch(function (err) {
global.clearTimeout(fetchTimer)
if (!self._destroyed)
self.emit('error', err)
})
}
read()
} else {
self._xhr = xhr
self._pos = 0
@@ -100,7 +136,15 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
inherits(IncomingMessage, stream.Readable)
IncomingMessage.prototype._read = function () {}
IncomingMessage.prototype._read = function () {
var self = this
var resolve = self._resumeFetch
if (resolve) {
self._resumeFetch = null
resolve()
}
}
IncomingMessage.prototype._onXHRProgress = function () {
var self = this
@@ -109,29 +153,12 @@ IncomingMessage.prototype._onXHRProgress = function () {
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
@@ -146,13 +173,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
@@ -161,7 +188,7 @@ 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
}
}
+15 -16
View File
@@ -1,6 +1,6 @@
{
"name": "stream-http",
"version": "2.5.0",
"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": "zuul --no-coverage -- test/browser/*.js",
"test-browser-local": "zuul --local 8080 --no-coverage -- test/browser/*.js"
"test-browser": "airtap --loopback airtap.local -- test/browser/*.js",
"test-browser-local": "airtap --no-instrument --local 8080 -- test/browser/*.js"
},
"author": "John Hiesey",
"license": "MIT",
@@ -27,20 +27,19 @@
"http-browserify"
],
"dependencies": {
"builtin-status-codes": "^2.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.1.0",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
"builtin-status-codes": "^3.0.0",
"inherits": "^2.0.4",
"readable-stream": "^3.6.0",
"xtend": "^4.0.2"
},
"devDependencies": {
"basic-auth": "^1.0.3",
"brfs": "^1.4.0",
"cookie-parser": "^1.3.5",
"express": "^4.13.0",
"tape": "^4.0.0",
"ua-parser-js": "^0.7.7",
"webworkify": "^1.0.2",
"zuul": "^3.10.3"
"airtap": "^3.0.0",
"basic-auth": "^2.0.1",
"brfs": "^2.0.2",
"cookie-parser": "^1.4.5",
"express": "^4.17.1",
"tape": "^5.0.0",
"ua-parser-js": "^0.7.21",
"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 or in Opera
var skipStreamingCheck = (browserName === 'Opera' || (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()
})
+29
View File
@@ -0,0 +1,29 @@
var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var http = require('../..')
var reference = fs.readFileSync(__dirname + '/../server/static/basic.txt')
test('get body empty', function (t) {
var req = http.request({
path: '/verifyEmpty',
method: 'GET'
}, function (res) {
var buffers = []
res.on('end', function () {
console.log(Buffer.concat(buffers).toString('utf8'))
t.ok(Buffer.from('empty').equals(Buffer.concat(buffers)), 'response body indicates request body was empty')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
req.write(reference)
req.end()
})
+46 -5
View File
@@ -46,6 +46,40 @@ test('headers', function (t) {
})
})
test('arrays of headers', function (t) {
http.get({
path: '/testHeaders?Response-Header=bar&Response-Header=BAR2',
headers: {
'Test-Request-Header': ['foo', 'FOO2']
}
}, function (res) {
var rawHeaders = []
for (var i = 0; i < res.rawHeaders.length; i += 2) {
var lowerKey = res.rawHeaders[i].toLowerCase()
if (lowerKey.indexOf('test-') === 0)
rawHeaders.push(lowerKey, res.rawHeaders[i + 1])
}
t.equal(rawHeaders[0], 'test-response-header', 'raw response header present')
t.equal(rawHeaders[1], 'bar, BAR2', 'raw response header value')
t.equal(rawHeaders.length, 2, 'correct number of raw headers')
t.equal(res.headers['test-response-header'], 'bar, BAR2', 'response header')
var buffers = []
res.on('end', function () {
var body = JSON.parse(Buffer.concat(buffers).toString())
t.equal(body['test-request-header'], 'foo,FOO2', 'request headers')
t.equal(Object.keys(body).length, 1, 'correct number of request headers')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
})
test('content-type response header', function (t) {
http.get('/testHeaders', function (res) {
t.equal(res.headers['content-type'], 'application/json', 'content-type preserved')
@@ -56,19 +90,26 @@ test('content-type response header', function (t) {
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
var browserMinorVersion = browser.minor || 0
// The content-type header is broken when 'prefer-streaming' or 'allow-wrong-content-type'
// is passed in browsers that rely on xhr.overrideMimeType(), namely older chrome and newer safari
// is passed in browsers that rely on xhr.overrideMimeType(), namely older chrome, safari 6-10.0, and the stock Android browser
// Note that Safari 10.0 on iOS 10.3 doesn't need to override the mime type, so the content-type is preserved.
var wrongMimeType = ((browserName === 'Chrome' && browserVersion <= 42) ||
((browserName === 'Safari' || browserName === 'Mobile Safari') && browserVersion >= 6))
((browserName === 'Safari' || browserName === 'Mobile Safari') && browserVersion >= 6 && (browserVersion < 10 || (browserVersion == 10 && browserMinorVersion == 0)))
|| (browserName === 'Android Browser'))
test('content-type response header with forced streaming', function (t) {
http.get({
path: '/testHeaders',
mode: 'prefer-streaming'
}, function (res) {
if (wrongMimeType)
t.equal(res.headers['content-type'], 'text/plain; charset=x-user-defined', 'content-type overridden')
else
if (wrongMimeType) {
// allow both the 'wrong' and correct mime type, since sometimes it's impossible to tell which to expect
// from the browser version alone (e.g. Safari 10.0 on iOS 10.2 vs iOS 10.3)
var contentType = res.headers['content-type']
var correct = (contentType === 'text/plain; charset=x-user-defined') || (contentType === 'application/json')
t.ok(correct, 'content-type either preserved or overridden')
} else
t.equal(res.headers['content-type'], 'application/json', 'content-type preserved')
t.end()
})
+1 -14
View File
@@ -5,16 +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 === 'Opera' && browserVersion <= 11) ||
(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) {
@@ -25,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()
})
+3 -6
View File
@@ -8,8 +8,8 @@ var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Streaming doesn't work in IE9 or below or in Opera
var skipStreamingCheck = (browserName === 'Opera' || (browserName === 'IE' && browserVersion <= 9))
// Streaming doesn't work in IE9 or below
var skipStreamingCheck = (browserName === 'IE' && browserVersion <= 9)
var COPIES = 1000
var MIN_PIECES = 5
@@ -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 -3
View File
@@ -10,13 +10,11 @@ var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
// Response urls don't work on many browsers
var skipResponseUrl = ((browserName === 'Opera') ||
(browserName === 'IE') ||
var skipResponseUrl = ((browserName === 'IE') ||
(browserName === 'Edge') ||
(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
View File
@@ -0,0 +1,43 @@
var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var http = require('../..')
test('timeout', function (t) {
var req = http.get({
path: '/browserify.png?copies=5',
requestTimeout: 10 // ms
}, function (res) {
res.on('data', function (data) {
})
res.on('end', function () {
t.fail('request completed (should have timed out)')
})
})
req.on('requestTimeout', function () {
t.pass('got timeout')
t.end()
})
})
// TODO: reenable this if there's a way to make it simultaneously
// fast and reliable
test.skip('no timeout 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 timeout')
})
})
+2 -13
View File
@@ -4,21 +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 === 'Opera' && browserVersion <= 12) ||
(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')
+15 -1
View File
@@ -1,4 +1,4 @@
// These tests are teken from http-browserify to ensure compatibility with
// These tests are taken from http-browserify to ensure compatibility with
// that module
var test = require('tape')
var url = require('url')
@@ -17,6 +17,20 @@ var moduleName = require.resolve('../../')
delete require.cache[moduleName]
var http = require('../../')
test('Make sure http object has correct properties', function (t) {
t.ok(http.Agent, 'Agent defined')
t.ok(http.ClientRequest, 'ClientRequest defined')
t.ok(http.ClientRequest.prototype, 'ClientRequest.prototype defined')
t.ok(http.IncomingMessage, 'IncomingMessage defined')
t.ok(http.IncomingMessage.prototype, 'IncomingMessage.prototype defined')
t.ok(http.METHODS, 'METHODS defined')
t.ok(http.STATUS_CODES, 'STATUS_CODES defined')
t.ok(http.get, 'get defined')
t.ok(http.globalAgent, 'globalAgent defined')
t.ok(http.request, 'request defined')
t.end()
})
test('Test simple url string', function(t) {
var testUrl = { path: '/api/foo' }
var request = http.get(testUrl, noop)
+25 -3
View File
@@ -32,13 +32,17 @@ app.get('/testHeaders', function (req, res) {
})
res.setHeader('Content-Type', 'application/json')
res.setHeader('Cache-Control', 'no-cache')
// Request headers are sent in the body as json
var reqHeaders = {}
Object.keys(req.headers).forEach(function (key) {
key = key.toLowerCase()
if (key.indexOf('test-') === 0)
reqHeaders[key] = req.headers[key]
if (key.indexOf('test-') === 0) {
// different browsers format request headers with multiple values
// slightly differently, so normalize
reqHeaders[key] = req.headers[key].replace(', ', ',')
}
})
var body = JSON.stringify(reqHeaders)
@@ -71,6 +75,24 @@ app.post('/echo', function (req, res) {
req.pipe(res)
})
app.use('/verifyEmpty', function (req, res) {
var empty = true
req.on('data', function (buf) {
if (buf.length > 0) {
empty = false
}
})
req.on('end', function () {
res.setHeader('Content-Type', 'text/plain')
if (empty) {
res.end('empty')
} else {
res.end('not empty')
}
})
})
app.use(function (req, res, next) {
var parsed = url.parse(req.url, true)
@@ -110,6 +132,6 @@ app.use(function (req, res, next) {
app.use(express.static(path.join(__dirname, 'static')))
var port = parseInt(process.env.ZUUL_PORT) || 8199
var port = parseInt(process.env.AIRTAP_PORT) || 8199
console.log('Test server listening on port', port)
server.listen(port)
-1
View File
@@ -1 +0,0 @@
../../../ie8-polyfill.js