stream-http-2.7.2/ 0000775 0000000 0000000 00000000000 13117573734 0014005 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/.gitignore 0000664 0000000 0000000 00000000067 13117573734 0016000 0 ustar 00root root 0000000 0000000 .DS_Store
bundle.js
node_modules
npm-debug.log
.zuulrc
stream-http-2.7.2/.travis.yml 0000664 0000000 0000000 00000000044 13117573734 0016114 0 ustar 00root root 0000000 0000000 language: node_js
node_js:
- "6.4" stream-http-2.7.2/.zuul.yml 0000664 0000000 0000000 00000000672 13117573734 0015612 0 ustar 00root root 0000000 0000000 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.4..latest'
server: ./test/server/index.js
scripts:
- "/ie8-polyfill.js"
- "/test-polyfill.js"
stream-http-2.7.2/LICENSE 0000664 0000000 0000000 00000002076 13117573734 0015017 0 ustar 00root root 0000000 0000000 The MIT License
Copyright (c) 2015 John Hiesey
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stream-http-2.7.2/README.md 0000664 0000000 0000000 00000014555 13117573734 0015276 0 ustar 00root root 0000000 0000000 # stream-http [](https://travis-ci.org/jhiesey/stream-http)
[](https://saucelabs.com/u/stream-http)
This module is an implementation of Node's native `http` module for the browser.
It tries to match Node's API and behavior as closely as possible, but some features
aren't available, since browsers don't give nearly as much control over requests.
This is heavily inspired by, and intended to replace, [http-browserify](https://github.com/substack/http-browserify).
## What does it do?
In accordance with its name, `stream-http` tries to provide data to its caller before
the request has completed whenever possible.
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 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.
## How do you use it?
The intent is to have the same API as the client part of the
[Node HTTP module](https://nodejs.org/api/http.html). The interfaces are the same wherever
practical, although limitations in browsers make an exact clone of the Node API impossible.
This module implements `http.request`, `http.get`, and most of `http.ClientRequest`
and `http.IncomingMessage` in addition to `http.METHODS` and `http.STATUS_CODES`. See the
Node docs for how these work.
### Extra features compared to Node
* The `message.url` property provides access to the final URL after all redirects. This
is useful since the browser follows all redirects silently, unlike Node. It is available
in Chrome 37 and newer, Firefox 32 and newer, and Safari 9 and newer.
* The `options.withCredentials` boolean flag, used to indicate if the browser should send
cookies or authentication information with a CORS request. Default false.
This module has to make some tradeoffs to support binary data and/or streaming. Generally,
the module can make a fairly good decision about which underlying browser features to use,
but sometimes it helps to get a little input from the developer.
* The `options.mode` field passed into `http.request` or `http.get` can take on one of the
following values:
* 'default' (or any falsy value, including `undefined`): Try to provide partial data before
the request completes, but not at the cost of correctness for binary data or correctness of
the 'content-type' response header. This mode will also avoid slower code paths whenever
possible, which is particularly useful when making large requests in a browser like Safari
that has a weaker JavaScript engine.
* 'allow-wrong-content-type': Provides partial data in more cases than 'default', but
at the expense of causing the 'content-type' response header to be incorrectly reported
(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
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').
* 'disable-fetch': Force the use of plain XHR regardless of the browser declaring a fetch
capability. Preserves the correctness of binary data and the 'content-type' response header.
* 'prefer-fast': Deprecated; now a synonym for 'default', which has the same performance
characteristics as this mode did in versions before 1.5.
### Features missing compared to Node
* `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
socket.
* Any options that are disallowed for security reasons. This includes setting or getting
certain headers.
* `message.httpVersion`
* `message.rawHeaders` is modified by the browser, and may not quite match what is sent by
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` options in the `request` method is non-operational in Safari <= 5 and
Opera <= 12.
## Example
``` js
http.get('/bundle.js', function (res) {
var div = document.getElementById('result');
div.innerHTML += 'GET /beep
';
res.on('data', function (buf) {
div.innerHTML += buf;
});
res.on('end', function () {
div.innerHTML += '
__END__';
});
})
```
## Running tests
There are two sets of tests: the tests that run in Node (found in `test/node`) and the tests
that run in the browser (found in `test/browser`). Normally the browser tests run on
[Sauce Labs](http://saucelabs.com/).
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).
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`
## License
MIT. Copyright (C) John Hiesey and other contributors.
stream-http-2.7.2/ie8-polyfill.js 0000664 0000000 0000000 00000011442 13117573734 0016662 0 ustar 00root root 0000000 0000000 // 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;
};
} stream-http-2.7.2/index.js 0000664 0000000 0000000 00000003266 13117573734 0015461 0 ustar 00root root 0000000 0000000 var ClientRequest = require('./lib/request')
var extend = require('xtend')
var statusCodes = require('builtin-status-codes')
var url = require('url')
var http = exports
http.request = function (opts, cb) {
if (typeof opts === 'string')
opts = url.parse(opts)
else
opts = extend(opts)
// Normally, the page is loaded from http or https, so not specifying a protocol
// will result in a (valid) protocol-relative url. However, this won't work if
// the protocol is something else, like 'file:'
var defaultProtocol = global.location.protocol.search(/^https?:$/) === -1 ? 'http:' : ''
var protocol = opts.protocol || defaultProtocol
var host = opts.hostname || opts.host
var port = opts.port
var path = opts.path || '/'
// Necessary for IPv6 addresses
if (host && host.indexOf(':') !== -1)
host = '[' + host + ']'
// This may be a relative url. The browser should always be able to interpret it correctly.
opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path
opts.method = (opts.method || 'GET').toUpperCase()
opts.headers = opts.headers || {}
// Also valid opts.auth, opts.mode
var req = new ClientRequest(opts)
if (cb)
req.on('response', cb)
return req
}
http.get = function get (opts, cb) {
var req = http.request(opts, cb)
req.end()
return req
}
http.Agent = function () {}
http.Agent.defaultMaxSockets = 4
http.STATUS_CODES = statusCodes
http.METHODS = [
'CHECKOUT',
'CONNECT',
'COPY',
'DELETE',
'GET',
'HEAD',
'LOCK',
'M-SEARCH',
'MERGE',
'MKACTIVITY',
'MKCOL',
'MOVE',
'NOTIFY',
'OPTIONS',
'PATCH',
'POST',
'PROPFIND',
'PROPPATCH',
'PURGE',
'PUT',
'REPORT',
'SEARCH',
'SUBSCRIBE',
'TRACE',
'UNLOCK',
'UNSUBSCRIBE'
] stream-http-2.7.2/lib/ 0000775 0000000 0000000 00000000000 13117573734 0014553 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/lib/capability.js 0000664 0000000 0000000 00000004435 13117573734 0017240 0 ustar 00root root 0000000 0000000 exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)
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.
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
} catch (e) {}
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'))
// 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')
// 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'
}
xhr = null // Help gc
stream-http-2.7.2/lib/request.js 0000664 0000000 0000000 00000017132 13117573734 0016605 0 ustar 00root root 0000000 0000000 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
function decideMode (preferBinary, useFetch) {
if (capability.fetch && useFetch) {
return 'fetch'
} else if (capability.mozchunkedarraybuffer) {
return 'moz-chunked-arraybuffer'
} else if (capability.msstream) {
return 'ms-stream'
} else if (capability.arraybuffer && preferBinary) {
return 'arraybuffer'
} else if (capability.vbArray && preferBinary) {
return 'text:vbarray'
} else {
return 'text'
}
}
var ClientRequest = module.exports = function (opts) {
var self = this
stream.Writable.call(self)
self._opts = opts
self._body = []
self._headers = {}
if (opts.auth)
self.setHeader('Authorization', 'Basic ' + new Buffer(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' || 'timeout' in opts) {
// If the use of XHR should be preferred and includes preserving the 'content-type' header.
// Force XHR to be used since the Fetch API does not yet support timeouts.
useFetch = false
preferBinary = true
} else if (opts.mode === 'prefer-streaming') {
// If streaming is a high priority but binary compatibility and
// the accuracy of the 'content-type' header aren't
preferBinary = false
} else if (opts.mode === 'allow-wrong-content-type') {
// If streaming is more important than preserving the 'content-type' header
preferBinary = !capability.overrideMimeType
} else if (!opts.mode || opts.mode === 'default' || opts.mode === 'prefer-fast') {
// Use binary if text streaming may corrupt data or the content-type header, or for speed
preferBinary = true
} else {
throw new Error('Invalid value for opts.mode')
}
self._mode = decideMode(preferBinary, useFetch)
self.on('finish', function () {
self._onFinish()
})
}
inherits(ClientRequest, stream.Writable)
ClientRequest.prototype.setHeader = function (name, value) {
var self = this
var lowerName = name.toLowerCase()
// This check is not necessary, but it prevents warnings from browsers about setting unsafe
// headers. To be honest I'm not entirely sure hiding these warnings is a good thing, but
// http-browserify did it, so I will too.
if (unsafeHeaders.indexOf(lowerName) !== -1)
return
self._headers[lowerName] = {
name: name,
value: value
}
}
ClientRequest.prototype.getHeader = function (name) {
var header = this._headers[name.toLowerCase()]
if (header)
return header.value
return null
}
ClientRequest.prototype.removeHeader = function (name) {
var self = this
delete self._headers[name.toLowerCase()]
}
ClientRequest.prototype._onFinish = function () {
var self = this
if (self._destroyed)
return
var opts = self._opts
var headersObj = self._headers
var body = null
if (opts.method !== 'GET' && opts.method !== 'HEAD') {
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()
}
}
// 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 {
headersList.push([name, value])
}
})
if (self._mode === 'fetch') {
global.fetch(self._opts.url, {
method: self._opts.method,
headers: headersList,
body: body || undefined,
mode: 'cors',
credentials: opts.withCredentials ? 'include' : 'same-origin'
}).then(function (response) {
self._fetchResponse = response
self._connect()
}, function (reason) {
self.emit('error', reason)
})
} else {
var xhr = self._xhr = new global.XMLHttpRequest()
try {
xhr.open(self._opts.method, self._opts.url, true)
} catch (err) {
process.nextTick(function () {
self.emit('error', err)
})
return
}
// Can't set responseType on really old browsers
if ('responseType' in xhr)
xhr.responseType = self._mode.split(':')[0]
if ('withCredentials' in xhr)
xhr.withCredentials = !!opts.withCredentials
if (self._mode === 'text' && 'overrideMimeType' in xhr)
xhr.overrideMimeType('text/plain; charset=x-user-defined')
if ('timeout' in opts) {
xhr.timeout = opts.timeout
xhr.ontimeout = function () {
self.emit('timeout')
}
}
headersList.forEach(function (header) {
xhr.setRequestHeader(header[0], header[1])
})
self._response = null
xhr.onreadystatechange = function () {
switch (xhr.readyState) {
case rStates.LOADING:
case rStates.DONE:
self._onXHRProgress()
break
}
}
// Necessary for streaming in Firefox, since xhr.response is ONLY defined
// in onprogress, not in onreadystatechange with xhr.readyState = 3
if (self._mode === 'moz-chunked-arraybuffer') {
xhr.onprogress = function () {
self._onXHRProgress()
}
}
xhr.onerror = function () {
if (self._destroyed)
return
self.emit('error', new Error('XHR error'))
}
try {
xhr.send(body)
} catch (err) {
process.nextTick(function () {
self.emit('error', err)
})
return
}
}
}
/**
* Checks if xhr.status is readable and non-zero, indicating no error.
* Even though the spec says it should be available in readyState 3,
* accessing it throws an exception in IE8
*/
function statusValid (xhr) {
try {
var status = xhr.status
return (status !== null && status !== 0)
} catch (e) {
return false
}
}
ClientRequest.prototype._onXHRProgress = function () {
var self = this
if (!statusValid(self._xhr) || self._destroyed)
return
if (!self._response)
self._connect()
self._response._onXHRProgress()
}
ClientRequest.prototype._connect = function () {
var self = this
if (self._destroyed)
return
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode)
self._response.on('error', function(err) {
self.emit('error', err)
})
self.emit('response', self._response)
}
ClientRequest.prototype._write = function (chunk, encoding, cb) {
var self = this
self._body.push(chunk)
cb()
}
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () {
var self = this
self._destroyed = true
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
}
ClientRequest.prototype.end = function (data, encoding, cb) {
var self = this
if (typeof data === 'function') {
cb = data
data = undefined
}
stream.Writable.prototype.end.call(self, data, encoding, cb)
}
ClientRequest.prototype.flushHeaders = function () {}
ClientRequest.prototype.setTimeout = function () {}
ClientRequest.prototype.setNoDelay = function () {}
ClientRequest.prototype.setSocketKeepAlive = function () {}
// Taken from http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method
var unsafeHeaders = [
'accept-charset',
'accept-encoding',
'access-control-request-headers',
'access-control-request-method',
'connection',
'content-length',
'cookie',
'cookie2',
'date',
'dnt',
'expect',
'host',
'keep-alive',
'origin',
'referer',
'te',
'trailer',
'transfer-encoding',
'upgrade',
'user-agent',
'via'
]
stream-http-2.7.2/lib/response.js 0000664 0000000 0000000 00000011126 13117573734 0016750 0 ustar 00root root 0000000 0000000 var capability = require('./capability')
var inherits = require('inherits')
var stream = require('readable-stream')
var rStates = exports.readyStates = {
UNSENT: 0,
OPENED: 1,
HEADERS_RECEIVED: 2,
LOADING: 3,
DONE: 4
}
var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
var self = this
stream.Readable.call(self)
self._mode = mode
self.headers = {}
self.rawHeaders = []
self.trailers = {}
self.rawTrailers = []
// Fake the 'close' event, but only once 'end' fires
self.on('end', function () {
// The nextTick is necessary to prevent the 'request' module from causing an infinite loop
process.nextTick(function () {
self.emit('close')
})
})
if (mode === 'fetch') {
self._fetchResponse = response
self.url = response.url
self.statusCode = response.status
self.statusMessage = response.statusText
response.headers.forEach(function(header, key){
self.headers[key.toLowerCase()] = header
self.rawHeaders.push(key, header)
})
// TODO: this doesn't respect backpressure. Once WritableStream is available, this can be fixed
var reader = response.body.getReader()
function read () {
reader.read().then(function (result) {
if (self._destroyed)
return
if (result.done) {
self.push(null)
return
}
self.push(new Buffer(result.value))
read()
}).catch(function(err) {
self.emit('error', err)
})
}
read()
} else {
self._xhr = xhr
self._pos = 0
self.url = xhr.responseURL
self.statusCode = xhr.status
self.statusMessage = xhr.statusText
var headers = xhr.getAllResponseHeaders().split(/\r?\n/)
headers.forEach(function (header) {
var matches = header.match(/^([^:]+):\s*(.*)/)
if (matches) {
var key = matches[1].toLowerCase()
if (key === 'set-cookie') {
if (self.headers[key] === undefined) {
self.headers[key] = []
}
self.headers[key].push(matches[2])
} else if (self.headers[key] !== undefined) {
self.headers[key] += ', ' + matches[2]
} else {
self.headers[key] = matches[2]
}
self.rawHeaders.push(matches[1], matches[2])
}
})
self._charset = 'x-user-defined'
if (!capability.overrideMimeType) {
var mimeType = self.rawHeaders['mime-type']
if (mimeType) {
var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/)
if (charsetMatch) {
self._charset = charsetMatch[1].toLowerCase()
}
}
if (!self._charset)
self._charset = 'utf-8' // best guess
}
}
}
inherits(IncomingMessage, stream.Readable)
IncomingMessage.prototype._read = function () {}
IncomingMessage.prototype._onXHRProgress = function () {
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
}
if (response.length > self._pos) {
var newData = response.substr(self._pos)
if (self._charset === 'x-user-defined') {
var buffer = new Buffer(newData.length)
for (var i = 0; i < newData.length; i++)
buffer[i] = newData.charCodeAt(i) & 0xff
self.push(buffer)
} else {
self.push(newData, self._charset)
}
self._pos = response.length
}
break
case 'arraybuffer':
if (xhr.readyState !== rStates.DONE || !xhr.response)
break
response = xhr.response
self.push(new Buffer(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)))
break
case 'ms-stream':
response = xhr.response
if (xhr.readyState !== rStates.LOADING)
break
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._pos = reader.result.byteLength
}
}
reader.onload = function () {
self.push(null)
}
// reader.onerror = ??? // TODO: this
reader.readAsArrayBuffer(response)
break
}
// The ms-stream case handles end separately in reader.onload()
if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') {
self.push(null)
}
}
stream-http-2.7.2/package.json 0000664 0000000 0000000 00000002347 13117573734 0016301 0 ustar 00root root 0000000 0000000 {
"name": "stream-http",
"version": "2.7.2",
"description": "Streaming http in the browser",
"main": "index.js",
"repository": {
"type": "git",
"url": "git://github.com/jhiesey/stream-http.git"
},
"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"
},
"author": "John Hiesey",
"license": "MIT",
"bugs": {
"url": "https://github.com/jhiesey/stream-http/issues"
},
"homepage": "https://github.com/jhiesey/stream-http#readme",
"keywords": [
"http",
"stream",
"streaming",
"xhr",
"http-browserify"
],
"dependencies": {
"builtin-status-codes": "^3.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.2.6",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
},
"devDependencies": {
"basic-auth": "^1.0.3",
"brfs": "^1.4.0",
"cookie-parser": "^1.4.3",
"express": "^4.15.2",
"tape": "^4.0.0",
"ua-parser-js": "^0.7.7",
"webworkify": "^1.0.2",
"zuul": "^3.10.3"
}
}
stream-http-2.7.2/test/ 0000775 0000000 0000000 00000000000 13117573734 0014764 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/browser/ 0000775 0000000 0000000 00000000000 13117573734 0016447 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/browser/abort.js 0000664 0000000 0000000 00000002130 13117573734 0020110 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var http = require('../..')
test('abort before response', function (t) {
var req = http.get('/basic.txt', function (res) {
t.fail('unexpected response')
})
req.abort()
t.end()
})
test('abort on response', function (t) {
var req = http.get('/basic.txt', function (res) {
req.abort()
t.end()
res.on('end', function () {
t.fail('unexpected end')
})
res.on('data', function (data) {
t.fail('unexpected data')
})
})
})
test('abort on data', function (t) {
var req = http.get('/browserify.png?copies=5', function (res) {
var firstData = true
var failOnData = false
res.on('end', function () {
t.fail('unexpected end')
})
res.on('data', function (data) {
if (failOnData)
t.fail('unexpected data')
else if (firstData) {
firstData = false
req.abort()
t.end()
process.nextTick(function () {
// Wait for any data that may have been queued
// in the stream before considering data events
// as errors
failOnData = true
})
}
})
})
}) stream-http-2.7.2/test/browser/auth.js 0000664 0000000 0000000 00000000670 13117573734 0017751 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var test = require('tape')
var http = require('../..')
test('authentication', function (t) {
http.get({
path: '/auth',
auth: 'TestUser:trustno1'
}, function (res) {
var buffers = []
res.on('end', function () {
t.ok(new Buffer('You\'re in!').equals(Buffer.concat(buffers)), 'authentication succeeded')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
}) stream-http-2.7.2/test/browser/binary-streaming.js 0000664 0000000 0000000 00000004020 13117573734 0022254 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
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 MIN_PIECES = 2
var referenceOnce = fs.readFileSync(__dirname + '/../server/static/browserify.png')
var reference = new Buffer(referenceOnce.length * COPIES)
for(var i = 0; i < COPIES; i++) {
referenceOnce.copy(reference, referenceOnce.length * i)
}
test('binary streaming', function (t) {
http.get({
path: '/browserify.png?copies=' + COPIES,
mode: 'allow-wrong-content-type'
}, 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.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
})
test('large binary request without streaming', function (t) {
http.get({
path: '/browserify.png?copies=' + COPIES,
mode: 'default',
}, 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.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
}) stream-http-2.7.2/test/browser/binary.js 0000664 0000000 0000000 00000001540 13117573734 0020271 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
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) {
http.get('/browserify.png', 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.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
}) stream-http-2.7.2/test/browser/body-empty.js 0000664 0000000 0000000 00000001220 13117573734 0021071 0 ustar 00root root 0000000 0000000 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()
})
stream-http-2.7.2/test/browser/cookie.js 0000664 0000000 0000000 00000000776 13117573734 0020270 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var test = require('tape')
var http = require('../..')
test('cookie', function (t) {
var cookie = 'hello=world'
window.document.cookie = cookie
http.get({
path: '/cookie',
withCredentials: false
}, function (res) {
var buffers = []
res.on('end', function () {
t.ok(new Buffer(cookie).equals(Buffer.concat(buffers)), 'hello cookie echoed')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
})
stream-http-2.7.2/test/browser/disable-fetch.js 0000664 0000000 0000000 00000001326 13117573734 0021501 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var test = require('tape')
var http = require('../..')
test('disable fetch', function (t) {
var originalFetch
if (typeof fetch === 'function') {
originalFetch = fetch
}
var fetchCalled = false
fetch = function (input, options) {
fetchCalled = true
if (originalFetch) {
return originalFetch(input, options)
}
}
http.get({
path: '/browserify.png',
mode: 'disable-fetch'
}, function (res) {
t.ok(!fetchCalled, 'fetch was not called')
if (originalFetch) {
fetch = originalFetch
}
res.on('end', function () {
t.ok(res.headers['content-type'] === 'image/png', 'content-type was set correctly')
t.end()
})
res.on('data', function () {})
})
})
stream-http-2.7.2/test/browser/error.js.disabled 0000664 0000000 0000000 00000000430 13117573734 0021701 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var test = require('tape')
var http = require('../..')
test('error handling', function (t) {
var req = http.get('https://0.0.0.0:0/fail.txt')
req.on('error', function (err) {
t.ok(err && ('message' in err), 'got error')
t.end()
})
}) stream-http-2.7.2/test/browser/headers.js 0000664 0000000 0000000 00000010434 13117573734 0020422 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var UAParser = require('ua-parser-js')
var http = require('../..')
test('headers', function (t) {
http.get({
path: '/testHeaders?Response-Header=bar&Response-Header-2=BAR2',
headers: {
'Test-Request-Header': 'foo',
'Test-Request-Header-2': '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])
}
var header1Pos = rawHeaders.indexOf('test-response-header')
t.ok(header1Pos >= 0, 'raw response header 1 present')
t.equal(rawHeaders[header1Pos + 1], 'bar', 'raw response header value 1')
var header2Pos = rawHeaders.indexOf('test-response-header-2')
t.ok(header2Pos >= 0, 'raw response header 2 present')
t.equal(rawHeaders[header2Pos + 1], 'BAR2', 'raw response header value 2')
t.equal(rawHeaders.length, 4, 'correct number of raw headers')
t.equal(res.headers['test-response-header'], 'bar', 'response header 1')
t.equal(res.headers['test-response-header-2'], 'BAR2', 'response header 2')
var buffers = []
res.on('end', function () {
var body = JSON.parse(Buffer.concat(buffers).toString())
t.equal(body['test-request-header'], 'foo', 'request header 1')
t.equal(body['test-request-header-2'], 'FOO2', 'request header 2')
t.equal(Object.keys(body).length, 2, 'correct number of request headers')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
})
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')
t.end()
})
})
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, 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 && (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) {
// 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()
})
}) stream-http-2.7.2/test/browser/lib/ 0000775 0000000 0000000 00000000000 13117573734 0017215 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/browser/lib/webworker-worker.js 0000664 0000000 0000000 00000000613 13117573734 0023071 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var http = require('../../..')
module.exports = function (self) {
self.addEventListener('message', function (ev) {
var url = ev.data
http.get(url, function (res) {
var buffers = []
res.on('end', function () {
self.postMessage(Buffer.concat(buffers).buffer)
})
res.on('data', function (data) {
buffers.push(data)
})
})
})
} stream-http-2.7.2/test/browser/package.json 0000664 0000000 0000000 00000000062 13117573734 0020733 0 ustar 00root root 0000000 0000000 {
"browserify": {
"transform": [ "brfs" ]
}
}
stream-http-2.7.2/test/browser/post-binary.js 0000664 0000000 0000000 00000002265 13117573734 0021261 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
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) {
var req = http.request({
path: '/echo',
method: 'POST'
}, function (res) {
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.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
req.write(reference)
req.end()
}) stream-http-2.7.2/test/browser/post-text.js 0000664 0000000 0000000 00000001626 13117573734 0020761 0 ustar 00root root 0000000 0000000 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('post text', function (t) {
var req = http.request({
path: '/echo',
method: 'POST'
}, function (res) {
var buffers = []
res.on('end', function () {
t.ok(reference.equals(Buffer.concat(buffers)), 'echoed contents match')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
req.write(reference)
req.end()
})
test('post text with data in end()', function (t) {
var req = http.request({
path: '/echo',
method: 'POST'
}, function (res) {
var buffers = []
res.on('end', function () {
t.ok(reference.equals(Buffer.concat(buffers)), 'echoed contents match')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
req.end(reference)
}) stream-http-2.7.2/test/browser/text-streaming.js 0000664 0000000 0000000 00000002273 13117573734 0021764 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
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
// Streaming doesn't work in IE9 or below or in Opera
var skipStreamingCheck = (browserName === 'Opera' || (browserName === 'IE' && browserVersion <= 9))
var COPIES = 1000
var MIN_PIECES = 5
var referenceOnce = fs.readFileSync(__dirname + '/../server/static/basic.txt')
var reference = new Buffer(referenceOnce.length * COPIES)
for(var i = 0; i < COPIES; i++) {
referenceOnce.copy(reference, referenceOnce.length * i)
}
test('text streaming', function (t) {
http.get({
path: '/basic.txt?copies=' + COPIES,
mode: 'prefer-streaming'
}, function (res) {
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(reference.equals(Buffer.concat(buffers)), 'contents match')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
}) stream-http-2.7.2/test/browser/text.js 0000664 0000000 0000000 00000002612 13117573734 0017772 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var UAParser = require('ua-parser-js')
var url = require('url')
var http = require('../..')
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') ||
(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')
test('basic functionality', function (t) {
http.get('/basic.txt', function (res) {
if (!skipResponseUrl) {
var testUrl = url.resolve(global.location.href, '/basic.txt')
// Redirects aren't tested, but presumably only browser bugs
// would cause this to fail only after redirects.
t.equals(res.url, testUrl, 'response url correct')
}
var buffers = []
res.on('end', function () {
t.ok(reference.equals(Buffer.concat(buffers)), 'contents match')
t.end()
})
res.on('data', function (data) {
buffers.push(data)
})
})
}) stream-http-2.7.2/test/browser/timeout.js.disabled 0000664 0000000 0000000 00000001413 13117573734 0022240 0 ustar 00root root 0000000 0000000 var Buffer = require('buffer').Buffer
var fs = require('fs')
var test = require('tape')
var UAParser = require('ua-parser-js')
var url = require('url')
var http = require('../..')
var browser = (new UAParser()).setUA(navigator.userAgent).getBrowser()
var browserName = browser.name
var browserVersion = browser.major
var skipTimeout = ((browserName === 'Opera' && browserVersion <= 12) ||
(browserName === 'Safari' && browserVersion <= 5))
test('emits timeout events', function (t) {
if (skipTimeout) {
return t.skip('Browser does not support setting timeouts')
}
var req = http.request({
path: '/basic.txt',
timeout: 1
})
req.on('timeout', function () {
t.pass('timeout caught')
t.end() // the test will timeout if this does not happen
})
req.end()
})
stream-http-2.7.2/test/browser/webworker.js 0000664 0000000 0000000 00000002332 13117573734 0021014 0 ustar 00root root 0000000 0000000 var fs = require('fs')
var test = require('tape')
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) {
// 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')
var worker = work(require('./lib/webworker-worker.js'))
worker.addEventListener('message', function (ev) {
var data = new Buffer(new Uint8Array(ev.data))
t.ok(reference.equals(data), 'contents match')
t.end()
})
worker.postMessage(testUrl)
}) stream-http-2.7.2/test/node/ 0000775 0000000 0000000 00000000000 13117573734 0015711 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/node/http-browserify.js 0000664 0000000 0000000 00000006740 13117573734 0021426 0 ustar 00root root 0000000 0000000 // These tests are teken from http-browserify to ensure compatibility with
// that module
var test = require('tape')
var url = require('url')
var location = 'http://localhost:8081/foo/123'
var noop = function() {}
global.location = url.parse(location)
global.XMLHttpRequest = function() {
this.open = noop
this.send = noop
this.withCredentials = false
}
var moduleName = require.resolve('../../')
delete require.cache[moduleName]
var http = require('../../')
test('Test simple url string', function(t) {
var testUrl = { path: '/api/foo' }
var request = http.get(testUrl, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'http://localhost:8081/api/foo', 'Url should be correct')
t.end()
})
test('Test full url object', function(t) {
var testUrl = {
host: "localhost:8081",
hostname: "localhost",
href: "http://localhost:8081/api/foo?bar=baz",
method: "GET",
path: "/api/foo?bar=baz",
pathname: "/api/foo",
port: "8081",
protocol: "http:",
query: "bar=baz",
search: "?bar=baz",
slashes: true
}
var request = http.get(testUrl, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'http://localhost:8081/api/foo?bar=baz', 'Url should be correct')
t.end()
})
test('Test alt protocol', function(t) {
var params = {
protocol: "foo:",
hostname: "localhost",
port: "3000",
path: "/bar"
}
var request = http.get(params, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'foo://localhost:3000/bar', 'Url should be correct')
t.end()
})
test('Test page with \'file:\' protocol', function (t) {
var params = {
hostname: 'localhost',
port: 3000,
path: '/bar'
}
var fileLocation = 'file:///home/me/stuff/index.html'
var normalLocation = global.location
global.location = url.parse(fileLocation) // Temporarily change the location
var request = http.get(params, noop)
global.location = normalLocation // Reset the location
var resolved = url.resolve(fileLocation, request._opts.url)
t.equal(resolved, 'http://localhost:3000/bar', 'Url should be correct')
t.end()
})
test('Test string as parameters', function(t) {
var testUrl = '/api/foo'
var request = http.get(testUrl, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'http://localhost:8081/api/foo', 'Url should be correct')
t.end()
})
test('Test withCredentials param', function(t) {
var url = '/api/foo'
var request = http.get({ url: url, withCredentials: false }, noop)
t.equal(request._xhr.withCredentials, false, 'xhr.withCredentials should be false')
var request = http.get({ url: url, withCredentials: true }, noop)
t.equal(request._xhr.withCredentials, true, 'xhr.withCredentials should be true')
var request = http.get({ url: url }, noop)
t.equal(request._xhr.withCredentials, false, 'xhr.withCredentials should be false')
t.end()
})
test('Test ipv6 address', function(t) {
var testUrl = 'http://[::1]:80/foo'
var request = http.get(testUrl, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'http://[::1]:80/foo', 'Url should be correct')
t.end()
})
test('Test relative path in url', function(t) {
var params = { path: './bar' }
var request = http.get(params, noop)
var resolved = url.resolve(location, request._opts.url)
t.equal(resolved, 'http://localhost:8081/foo/bar', 'Url should be correct')
t.end()
})
test('Cleanup', function (t) {
delete global.location
delete global.XMLHttpRequest
delete require.cache[moduleName]
t.end()
})
stream-http-2.7.2/test/server/ 0000775 0000000 0000000 00000000000 13117573734 0016272 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/server/index.js 0000664 0000000 0000000 00000006456 13117573734 0017752 0 ustar 00root root 0000000 0000000 var cookieParser = require('cookie-parser')
var basicAuth = require('basic-auth')
var express = require('express')
var fs = require('fs')
var http = require('http')
var path = require('path')
var url = require('url')
var app = express()
var server = http.createServer(app)
// Otherwise, use 'application/octet-stream'
var copiesMimeTypes = {
'/basic.txt': 'text/plain'
}
var maxDelay = 5000 // ms
// This should make sure bodies aren't cached
// so the streaming tests always pass
app.use(function (req, res, next) {
res.setHeader('Cache-Control', 'no-store')
next()
})
app.get('/testHeaders', function (req, res) {
var parsed = url.parse(req.url, true)
// Values in query parameters are sent as response headers
Object.keys(parsed.query).forEach(function (key) {
res.setHeader('Test-' + key, parsed.query[key])
})
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) {
// different browsers format request headers with multiple values
// slightly differently, so normalize
reqHeaders[key] = req.headers[key].replace(', ', ',')
}
})
var body = JSON.stringify(reqHeaders)
res.setHeader('Content-Length', body.length)
res.write(body)
res.end()
})
app.get('/cookie', cookieParser(), function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('hello=' + req.cookies.hello)
res.end()
})
app.get('/auth', function (req, res) {
var user = basicAuth(req)
if (!user || user.name !== 'TestUser' || user.pass !== 'trustno1') {
res.setHeader('WWW-Authenticate', 'Basic realm="example"')
res.end('Access denied')
} else {
res.setHeader('Content-Type', 'text/plain')
res.write('You\'re in!')
res.end()
}
})
app.post('/echo', function (req, res) {
res.setHeader('Content-Type', 'application/octet-stream')
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)
if ('copies' in parsed.query) {
var totalCopies = parseInt(parsed.query.copies, 10)
function fail () {
res.statusCode = 500
res.end()
}
fs.readFile(path.join(__dirname, 'static', parsed.pathname), function (err, data) {
if (err)
return fail()
var mimeType = copiesMimeTypes[parsed.pathname] || 'application/octet-stream'
res.setHeader('Content-Type', mimeType)
res.setHeader('Content-Length', data.length * totalCopies)
var pieceDelay = maxDelay / totalCopies
if (pieceDelay > 100)
pieceDelay = 100
function write (copies) {
if (copies === 0)
return res.end()
res.write(data, function (err) {
if (err)
return fail()
setTimeout(write.bind(null, copies - 1), pieceDelay)
})
}
write(totalCopies)
})
return
}
next()
})
app.use(express.static(path.join(__dirname, 'static')))
var port = parseInt(process.env.ZUUL_PORT) || 8199
console.log('Test server listening on port', port)
server.listen(port)
stream-http-2.7.2/test/server/static/ 0000775 0000000 0000000 00000000000 13117573734 0017561 5 ustar 00root root 0000000 0000000 stream-http-2.7.2/test/server/static/basic.txt 0000664 0000000 0000000 00000000724 13117573734 0021406 0 ustar 00root root 0000000 0000000 Mary had a little lamb,
His fleece was white as snow,
And everywhere that Mary went,
The lamb was sure to go.
He followed her to school one day,
Which was against the rule,
It made the children laugh and play
To see a lamb at school.
And so the teacher turned it out,
But still it lingered near,
And waited patiently about,
Till Mary did appear.
"Why does the lamb love Mary so?"
The eager children cry.
"Why, Mary loves the lamb, you know."
The teacher did reply.
stream-http-2.7.2/test/server/static/ie8-polyfill.js 0000777 0000000 0000000 00000000000 13117573734 0026143 2../../../ie8-polyfill.js ustar 00root root 0000000 0000000 stream-http-2.7.2/test/server/static/test-polyfill.js 0000664 0000000 0000000 00000000352 13117573734 0022726 0 ustar 00root root 0000000 0000000 if (!String.prototype.trim) {
(function() {
// Make sure we trim BOM and NBSP
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
String.prototype.trim = function() {
return this.replace(rtrim, '');
};
})();
}