0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

23
web/node_modules/stream-http/.airtap.yml generated vendored Normal file
View file

@ -0,0 +1,23 @@
sauce_connect: true
browsers:
- name: chrome
version: 39..latest
- name: firefox
version: 34..latest
- name: safari
version: 8..latest
- name: MicrosoftEdge
version: 13..latest
- name: ie
version: 9..latest
- name: iphone
version: '9.3..latest'
- name: android
version: '4.4..6.0' # TODO: change this back to latest once https://github.com/airtap/browsers/issues/3 is fixed
server: ./test/server/index.js
scripts:
- "/ie8-polyfill.js"
- "/test-polyfill.js"
browserify:
- options:
dedupe: false

7
web/node_modules/stream-http/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,7 @@
language: node_js
node_js:
- "node"
addons:
sauce_connect: true
hosts:
- airtap.local

24
web/node_modules/stream-http/LICENSE generated vendored Normal file
View file

@ -0,0 +1,24 @@
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.

144
web/node_modules/stream-http/README.md generated vendored Normal file
View file

@ -0,0 +1,144 @@
# stream-http [![Build Status](https://travis-ci.org/jhiesey/stream-http.svg?branch=master)](https://travis-ci.org/jhiesey/stream-http)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/stream-http.svg)](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.
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 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.
* `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
* 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` event/option and `setTimeout` functions, which operate on the underlying
socket, are not available. However, see `options.requestTimeout` above.
## Example
``` js
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__';
});
})
```
## 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.

168
web/node_modules/stream-http/ie8-polyfill.js generated vendored Normal file
View file

@ -0,0 +1,168 @@
// 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;
};
}

85
web/node_modules/stream-http/index.js generated vendored Normal file
View file

@ -0,0 +1,85 @@
var ClientRequest = require('./lib/request')
var response = require('./lib/response')
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.ClientRequest = ClientRequest
http.IncomingMessage = response.IncomingMessage
http.Agent = function () {}
http.Agent.defaultMaxSockets = 4
http.globalAgent = new http.Agent()
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'
]

73
web/node_modules/stream-http/lib/capability.js generated vendored Normal file
View file

@ -0,0 +1,73 @@
exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)
exports.writableStream = isFunction(global.WritableStream)
exports.abortController = isFunction(global.AbortController)
exports.blobConstructor = false
try {
new Blob([new ArrayBuffer(1)])
exports.blobConstructor = true
} catch (e) {}
// The xhr request to example.com may violate some restrictive CSP configurations,
// so if we're running in a browser that supports `fetch`, avoid calling getXHR()
// and assume support for certain features below.
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

327
web/node_modules/stream-http/lib/request.js generated vendored Normal file
View file

@ -0,0 +1,327 @@
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' || ('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') {
// 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._fetchTimer = null
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.arraybuffer) {
body = toArrayBuffer(Buffer.concat(self._body))
} else if (capability.blobConstructor) {
body = new global.Blob(self._body.map(function (buffer) {
return toArrayBuffer(buffer)
}), {
type: (headersObj['content-type'] || {}).value || ''
})
} else {
// get utf8 string
body = Buffer.concat(self._body).toString()
}
}
// 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') {
var signal = null
var fetchTimer = 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: headersList,
body: body || undefined,
mode: 'cors',
credentials: opts.withCredentials ? 'include' : 'same-origin',
signal: signal
}).then(function (response) {
self._fetchResponse = response
self._connect()
}, function (reason) {
global.clearTimeout(self._fetchTimer)
if (!self._destroyed)
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 ('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
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._fetchTimer)
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
global.clearTimeout(self._fetchTimer)
if (self._response)
self._response._destroyed = true
if (self._xhr)
self._xhr.abort()
else if (self._fetchAbortController)
self._fetchAbortController.abort()
}
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',
'via'
]

224
web/node_modules/stream-http/lib/response.js generated vendored Normal file
View file

@ -0,0 +1,224 @@
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, fetchTimer) {
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)
})
if (capability.writableStream) {
var writable = new WritableStream({
write: function (chunk) {
return new Promise(function (resolve, reject) {
if (self._destroyed) {
reject()
} else if(self.push(new Buffer(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)
}
})
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))
read()
}).catch(function (err) {
global.clearTimeout(fetchTimer)
if (!self._destroyed)
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 () {
var self = this
var resolve = self._resumeFetch
if (resolve) {
self._resumeFetch = null
resolve()
}
}
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)
}
}

46
web/node_modules/stream-http/package.json generated vendored Normal file
View file

@ -0,0 +1,46 @@
{
"name": "stream-http",
"version": "2.8.3",
"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": "airtap --loopback airtap.local -- test/browser/*.js",
"test-browser-local": "airtap --no-instrument --local 8080 -- 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.3.6",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
},
"devDependencies": {
"airtap": "^0.0.5",
"basic-auth": "^2.0.0",
"brfs": "^1.6.1",
"cookie-parser": "^1.4.3",
"express": "^4.16.3",
"tape": "^4.9.0",
"ua-parser-js": "^0.7.18",
"webworkify": "^1.5.0"
}
}

55
web/node_modules/stream-http/test/browser/abort.js generated vendored Normal file
View file

@ -0,0 +1,55 @@
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
})
}
})
})
})

22
web/node_modules/stream-http/test/browser/auth.js generated vendored Normal file
View file

@ -0,0 +1,22 @@
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)
})
})
})

View file

@ -0,0 +1,71 @@
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
var skipStreamingCheck = (browserName === 'IE' && browserVersion <= 10)
// Binary data gets corrupted in IE8 or below
var skipVerification = (browserName === 'IE' && browserVersion <= 8)
// IE8 tends to throw up modal dialogs complaining about scripts running too long
// Since streaming doesn't actually work there anyway, just use one copy
var COPIES = skipVerification ? 1 : 20
var 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)
})
})
})

32
web/node_modules/stream-http/test/browser/binary.js generated vendored Normal file
View file

@ -0,0 +1,32 @@
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)
})
})
})

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()
})

25
web/node_modules/stream-http/test/browser/cookie.js generated vendored Normal file
View file

@ -0,0 +1,25 @@
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)
})
})
})

View file

@ -0,0 +1,37 @@
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 () {})
})
})

View file

@ -0,0 +1,12 @@
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()
})
})

116
web/node_modules/stream-http/test/browser/headers.js generated vendored Normal file
View file

@ -0,0 +1,116 @@
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()
})
})

View file

@ -0,0 +1,20 @@
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)
})
})
})
}

View file

@ -0,0 +1,5 @@
{
"browserify": {
"transform": [ "brfs" ]
}
}

View file

@ -0,0 +1,41 @@
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 === '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()
})

48
web/node_modules/stream-http/test/browser/post-text.js generated vendored Normal file
View file

@ -0,0 +1,48 @@
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)
})

View file

@ -0,0 +1,43 @@
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
var skipStreamingCheck = (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)
})
})
})

43
web/node_modules/stream-http/test/browser/text.js generated vendored Normal file
View file

@ -0,0 +1,43 @@
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 === '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)
})
})
})

43
web/node_modules/stream-http/test/browser/timeout.js generated vendored Normal file
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')
})
})

31
web/node_modules/stream-http/test/browser/webworker.js generated vendored Normal file
View file

@ -0,0 +1,31 @@
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 === '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)
})

View file

@ -0,0 +1,147 @@
// These tests are taken 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('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)
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()
})

137
web/node_modules/stream-http/test/server/index.js generated vendored Normal file
View file

@ -0,0 +1,137 @@
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.AIRTAP_PORT) || 8199
console.log('Test server listening on port', port)
server.listen(port)

View file

@ -0,0 +1,19 @@
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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -0,0 +1,9 @@
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, '');
};
})();
}