Add local modules to fix http headers privacy problem
This commit is contained in:
parent
8838234e09
commit
2c173c6300
47
local_modules/web3-providers-http/README.md
Normal file
47
local_modules/web3-providers-http/README.md
Normal file
@ -0,0 +1,47 @@
|
||||
# web3-providers-http
|
||||
|
||||
[![NPM Package][npm-image]][npm-url] [![Dependency Status][deps-image]][deps-url] [![Dev Dependency Status][deps-dev-image]][deps-dev-url]
|
||||
|
||||
Package forked from https://github.com/ChainSafe/web3.js/tree/v1.6.1/packages/web3-providers-http to change http headers
|
||||
|
||||
This is a HTTP provider sub-package for [web3.js][repo].
|
||||
|
||||
Please read the [documentation][docs] for more.
|
||||
|
||||
## Installation
|
||||
|
||||
### Node.js
|
||||
|
||||
```bash
|
||||
npm install web3-providers-http
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const Web3HttpProvider = require('web3-providers-http');
|
||||
|
||||
const options = {
|
||||
keepAlive: true,
|
||||
timeout: 20000, // milliseconds,
|
||||
headers: [{name: 'Access-Control-Allow-Origin', value: '*'},{...}],
|
||||
withCredentials: false,
|
||||
agent: {http: http.Agent(...), baseUrl: ''}
|
||||
};
|
||||
|
||||
const provider = new Web3HttpProvider('http://localhost:8545', options);
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
All the TypeScript typings are placed in the `types` folder.
|
||||
|
||||
[docs]: http://web3js.readthedocs.io/en/1.0/
|
||||
[repo]: https://github.com/ethereum/web3.js
|
||||
[npm-image]: https://img.shields.io/npm/dm/web3-providers-http.svg
|
||||
[npm-url]: https://npmjs.org/package/web3-providers-http
|
||||
[deps-image]: https://david-dm.org/ethereum/web3.js/1.x/status.svg?path=packages/web3-providers-http
|
||||
[deps-url]: https://david-dm.org/ethereum/web3.js/1.x?path=packages/web3-providers-http
|
||||
[deps-dev-image]: https://david-dm.org/ethereum/web3.js/1.x/dev-status.svg?path=packages/web3-providers-http
|
||||
[deps-dev-url]: https://david-dm.org/ethereum/web3.js/1.x?type=dev&path=packages/web3-providers-http
|
125
local_modules/web3-providers-http/lib/index.js
Normal file
125
local_modules/web3-providers-http/lib/index.js
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file httpprovider.js
|
||||
* @authors:
|
||||
* Marek Kotewicz <marek@parity.io>
|
||||
* Marian Oancea
|
||||
* Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2015
|
||||
*/
|
||||
var errors = require('web3-core-helpers').errors;
|
||||
var XHR2 = require('xhr2-cookies').XMLHttpRequest; // jshint ignore: line
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
/**
|
||||
* HttpProvider should be used to send rpc calls over http
|
||||
*/
|
||||
var HttpProvider = function HttpProvider(host, options) {
|
||||
options = options || {};
|
||||
this.withCredentials = options.withCredentials || false;
|
||||
this.timeout = options.timeout || 0;
|
||||
this.headers = options.headers;
|
||||
this.agent = options.agent;
|
||||
this.connected = false;
|
||||
// keepAlive is true unless explicitly set to false
|
||||
const keepAlive = options.keepAlive !== false;
|
||||
this.host = host || 'http://localhost:8545';
|
||||
if (!this.agent) {
|
||||
if (this.host.substring(0, 5) === "https") {
|
||||
this.httpsAgent = new https.Agent({ keepAlive });
|
||||
}
|
||||
else {
|
||||
this.httpAgent = new http.Agent({ keepAlive });
|
||||
}
|
||||
}
|
||||
};
|
||||
HttpProvider.prototype._prepareRequest = function () {
|
||||
var request;
|
||||
// the current runtime is a browser
|
||||
if (typeof XMLHttpRequest !== 'undefined') {
|
||||
request = new XMLHttpRequest();
|
||||
}
|
||||
else {
|
||||
request = new XHR2();
|
||||
var agents = { httpsAgent: this.httpsAgent, httpAgent: this.httpAgent, baseUrl: this.baseUrl };
|
||||
if (this.agent) {
|
||||
agents.httpsAgent = this.agent.https;
|
||||
agents.httpAgent = this.agent.http;
|
||||
agents.baseUrl = this.agent.baseUrl;
|
||||
}
|
||||
request.nodejsSet(agents);
|
||||
}
|
||||
request.open('POST', this.host, true);
|
||||
request.setRequestHeader('Content-Type', 'application/json');
|
||||
request.timeout = this.timeout;
|
||||
request.withCredentials = this.withCredentials;
|
||||
if (this.headers) {
|
||||
this.headers.forEach(function (header) {
|
||||
request.setRequestHeader(header.name, header.value);
|
||||
});
|
||||
}
|
||||
return request;
|
||||
};
|
||||
/**
|
||||
* Should be used to make async request
|
||||
*
|
||||
* @method send
|
||||
* @param {Object} payload
|
||||
* @param {Function} callback triggered on end with (err, result)
|
||||
*/
|
||||
HttpProvider.prototype.send = function (payload, callback) {
|
||||
var _this = this;
|
||||
var request = this._prepareRequest();
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4 && request.timeout !== 1) {
|
||||
var result = request.responseText;
|
||||
var error = null;
|
||||
try {
|
||||
result = JSON.parse(result);
|
||||
}
|
||||
catch (e) {
|
||||
error = errors.InvalidResponse(request.responseText);
|
||||
}
|
||||
_this.connected = true;
|
||||
callback(error, result);
|
||||
}
|
||||
};
|
||||
request.ontimeout = function () {
|
||||
_this.connected = false;
|
||||
callback(errors.ConnectionTimeout(this.timeout));
|
||||
};
|
||||
try {
|
||||
request.send(JSON.stringify(payload));
|
||||
}
|
||||
catch (error) {
|
||||
this.connected = false;
|
||||
callback(errors.InvalidConnection(this.host));
|
||||
}
|
||||
};
|
||||
HttpProvider.prototype.disconnect = function () {
|
||||
//NO OP
|
||||
};
|
||||
/**
|
||||
* Returns the desired boolean.
|
||||
*
|
||||
* @method supportsSubscriptions
|
||||
* @returns {boolean}
|
||||
*/
|
||||
HttpProvider.prototype.supportsSubscriptions = function () {
|
||||
return false;
|
||||
};
|
||||
module.exports = HttpProvider;
|
6
local_modules/web3-providers-http/local_modules/xhr2-cookies/.gitignore
vendored
Normal file
6
local_modules/web3-providers-http/local_modules/xhr2-cookies/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
yarn-error.log
|
||||
.idea
|
||||
**/*.js
|
||||
**/*.js.map
|
||||
!wallaby.js
|
@ -0,0 +1,4 @@
|
||||
*
|
||||
.idea
|
||||
!dist/*
|
||||
!package.json
|
@ -0,0 +1,30 @@
|
||||
# XMLHttpRequest polyfill for node.js
|
||||
|
||||
Based on [https://github.com/pwnall/node-xhr2/tree/bd6d48431ad93c8073811e5d4b77394dd637a85a](https://github.com/pwnall/node-xhr2/tree/bd6d48431ad93c8073811e5d4b77394dd637a85a)
|
||||
|
||||
* Adds support for cookies
|
||||
* Adds in-project TypeScript type definitions
|
||||
* Switched to TypeScript
|
||||
|
||||
### Cookies
|
||||
|
||||
* saved in `XMLHttpRequest.cookieJar`
|
||||
* saved between redirects
|
||||
* saved between requests
|
||||
* can be cleared by doing:
|
||||
```typescript
|
||||
import * as Cookie from 'cookiejar';
|
||||
XMLHttpRequest.cookieJar = Cookie.CookieJar();
|
||||
```
|
||||
|
||||
### Aims
|
||||
|
||||
* Provide full XMLHttpRequest features to Angular Universal HttpClient &
|
||||
`node-angular-http-client`
|
||||
|
||||
### Changelog
|
||||
|
||||
#### `1.1.0`
|
||||
* added saving of cookies between requests, not just redirects
|
||||
* bug fixes
|
||||
* most tests from `xhr2` ported over and passing
|
8
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/errors.d.ts
vendored
Normal file
8
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/errors.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export declare class SecurityError extends Error {
|
||||
}
|
||||
export declare class InvalidStateError extends Error {
|
||||
}
|
||||
export declare class NetworkError extends Error {
|
||||
}
|
||||
export declare class SyntaxError extends Error {
|
||||
}
|
2
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/index.d.ts
vendored
Normal file
2
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './xml-http-request';
|
||||
export { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
11
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/progress-event.d.ts
vendored
Normal file
11
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/progress-event.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
import { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
export declare class ProgressEvent {
|
||||
type: string;
|
||||
bubbles: boolean;
|
||||
cancelable: boolean;
|
||||
target: XMLHttpRequestEventTarget;
|
||||
loaded: number;
|
||||
lengthComputable: boolean;
|
||||
total: number;
|
||||
constructor(type: string);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { ProgressEvent } from './progress-event';
|
||||
export declare type ProgressEventListener = (event: ProgressEvent) => void;
|
||||
export declare type ProgressEventListenerObject = {
|
||||
handleEvent(event: ProgressEvent): void;
|
||||
};
|
||||
export declare type ProgressEventListenerOrEventListenerObject = ProgressEventListener | ProgressEventListenerObject;
|
||||
export declare class XMLHttpRequestEventTarget {
|
||||
onloadstart: ProgressEventListener | null;
|
||||
onprogress: ProgressEventListener | null;
|
||||
onabort: ProgressEventListener | null;
|
||||
onerror: ProgressEventListener | null;
|
||||
onload: ProgressEventListener | null;
|
||||
ontimeout: ProgressEventListener | null;
|
||||
onloadend: ProgressEventListener | null;
|
||||
private listeners;
|
||||
addEventListener(eventType: string, listener?: ProgressEventListenerOrEventListenerObject): void;
|
||||
removeEventListener(eventType: string, listener?: ProgressEventListenerOrEventListenerObject): void;
|
||||
dispatchEvent(event: ProgressEvent): boolean;
|
||||
}
|
12
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.d.ts
vendored
Normal file
12
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/// <reference types="node" />
|
||||
import { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
import { ClientRequest } from 'http';
|
||||
export declare class XMLHttpRequestUpload extends XMLHttpRequestEventTarget {
|
||||
private _contentType;
|
||||
private _body;
|
||||
constructor();
|
||||
_reset(): void;
|
||||
_setData(data?: string | Buffer | ArrayBuffer | ArrayBufferView): void;
|
||||
_finalizeHeaders(headers: object, loweredHeaders: object): void;
|
||||
_startUpload(request: ClientRequest): void;
|
||||
}
|
102
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.d.ts
vendored
Normal file
102
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.d.ts
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/// <reference types="node" />
|
||||
import { ProgressEvent } from './progress-event';
|
||||
import { InvalidStateError, NetworkError, SecurityError, SyntaxError } from './errors';
|
||||
import { ProgressEventListener, XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
import { XMLHttpRequestUpload } from './xml-http-request-upload';
|
||||
import { Url } from 'url';
|
||||
import { Agent as HttpAgent } from 'http';
|
||||
import { Agent as HttpsAgent } from 'https';
|
||||
export interface XMLHttpRequestOptions {
|
||||
anon?: boolean;
|
||||
}
|
||||
export interface XHRUrl extends Url {
|
||||
method?: string;
|
||||
}
|
||||
export declare class XMLHttpRequest extends XMLHttpRequestEventTarget {
|
||||
static ProgressEvent: typeof ProgressEvent;
|
||||
static InvalidStateError: typeof InvalidStateError;
|
||||
static NetworkError: typeof NetworkError;
|
||||
static SecurityError: typeof SecurityError;
|
||||
static SyntaxError: typeof SyntaxError;
|
||||
static XMLHttpRequestUpload: typeof XMLHttpRequestUpload;
|
||||
static UNSENT: number;
|
||||
static OPENED: number;
|
||||
static HEADERS_RECEIVED: number;
|
||||
static LOADING: number;
|
||||
static DONE: number;
|
||||
static cookieJar: any;
|
||||
UNSENT: number;
|
||||
OPENED: number;
|
||||
HEADERS_RECEIVED: number;
|
||||
LOADING: number;
|
||||
DONE: number;
|
||||
onreadystatechange: ProgressEventListener | null;
|
||||
readyState: number;
|
||||
response: string | ArrayBuffer | Buffer | object | null;
|
||||
responseText: string;
|
||||
responseType: string;
|
||||
status: number;
|
||||
statusText: string;
|
||||
timeout: number;
|
||||
upload: XMLHttpRequestUpload;
|
||||
responseUrl: string;
|
||||
withCredentials: boolean;
|
||||
nodejsHttpAgent: HttpsAgent;
|
||||
nodejsHttpsAgent: HttpsAgent;
|
||||
nodejsBaseUrl: string | null;
|
||||
private _anonymous;
|
||||
private _method;
|
||||
private _url;
|
||||
private _sync;
|
||||
private _headers;
|
||||
private _loweredHeaders;
|
||||
private _mimeOverride;
|
||||
private _request;
|
||||
private _response;
|
||||
private _responseParts;
|
||||
private _responseHeaders;
|
||||
private _aborting;
|
||||
private _error;
|
||||
private _loadedBytes;
|
||||
private _totalBytes;
|
||||
private _lengthComputable;
|
||||
private _restrictedMethods;
|
||||
private _restrictedHeaders;
|
||||
private _privateHeaders;
|
||||
private _userAgent;
|
||||
constructor(options?: XMLHttpRequestOptions);
|
||||
open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
|
||||
setRequestHeader(name: string, value: any): void;
|
||||
send(data?: string | Buffer | ArrayBuffer | ArrayBufferView): void;
|
||||
abort(): void;
|
||||
getResponseHeader(name: string): string;
|
||||
getAllResponseHeaders(): string;
|
||||
overrideMimeType(mimeType: string): void;
|
||||
nodejsSet(options: {
|
||||
httpAgent?: HttpAgent;
|
||||
httpsAgent?: HttpsAgent;
|
||||
baseUrl?: string;
|
||||
}): void;
|
||||
static nodejsSet(options: {
|
||||
httpAgent?: HttpAgent;
|
||||
httpsAgent?: HttpsAgent;
|
||||
baseUrl?: string;
|
||||
}): void;
|
||||
private _setReadyState(readyState);
|
||||
private _sendFile(data);
|
||||
private _sendHttp(data?);
|
||||
private _sendHxxpRequest();
|
||||
private _finalizeHeaders();
|
||||
private _onHttpResponse(request, response);
|
||||
private _onHttpResponseData(response, data);
|
||||
private _onHttpResponseEnd(response);
|
||||
private _onHttpResponseClose(response);
|
||||
private _onHttpTimeout(request);
|
||||
private _onHttpRequestError(request, error);
|
||||
private _dispatchProgress(eventType);
|
||||
private _setError();
|
||||
private _parseUrl(urlString, user?, password?);
|
||||
private _parseResponseHeaders(response);
|
||||
private _parseResponse();
|
||||
private _parseResponseEncoding();
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export class SecurityError extends Error {}
|
||||
export class InvalidStateError extends Error {}
|
||||
export class NetworkError extends Error {}
|
||||
export class SyntaxError extends Error {}
|
@ -0,0 +1,2 @@
|
||||
export * from './xml-http-request';
|
||||
export { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "xhr2-cookies",
|
||||
"version": "1.1.0",
|
||||
"author": "Ionut Costica <ionut.costica@gmail.com>",
|
||||
"license": "MIT",
|
||||
"description": "XMLHttpRequest polyfill for node.js",
|
||||
"repository": "git://github.com/souldreamer/xhr2-cookies.git",
|
||||
"keywords": [
|
||||
"XMLHttpRequest",
|
||||
"cookies",
|
||||
"xhr2"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"dependencies": {
|
||||
"cookiejar": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/body-parser": "^1.16.8",
|
||||
"@types/cookie-parser": "^1.4.1",
|
||||
"@types/express": "^4.0.39",
|
||||
"@types/morgan": "^1.7.35",
|
||||
"@types/node": "^6",
|
||||
"ava": "^0.23.0",
|
||||
"ava-ts": "^0.23.0",
|
||||
"body-parser": "^1.18.2",
|
||||
"cookie-parser": "^1.4.3",
|
||||
"express": "^4.16.2",
|
||||
"morgan": "^1.9.0",
|
||||
"ts-loader": "^2.3.4",
|
||||
"ts-node": "^3.3.0",
|
||||
"typescript": "^2.5.2",
|
||||
"webpack": "^3.5.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "tsc",
|
||||
"test": "tsc -p ./test && ava-ts -v"
|
||||
},
|
||||
"ava": {
|
||||
"files": [
|
||||
"test/*.spec.ts"
|
||||
],
|
||||
"source": [
|
||||
"*.ts",
|
||||
"!dist/**/*"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
|
||||
export class ProgressEvent {
|
||||
bubbles = false;
|
||||
cancelable = false;
|
||||
target: XMLHttpRequestEventTarget;
|
||||
loaded = 0;
|
||||
lengthComputable = false;
|
||||
total = 0;
|
||||
|
||||
constructor (public type: string) {}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
import * as Cookie from 'cookiejar';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
XMLHttpRequest.cookieJar = Cookie.CookieJar();
|
||||
});
|
||||
|
||||
test('XMLHttpRequest sets cookies and passes them on on redirect', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(1);
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/redirect-cookie/test/works`);
|
||||
xhr.withCredentials = true;
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.responseText, 'works');
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest sets cookies and uses them for subsequent calls', async t => {
|
||||
let xhr = t.context.xhr;
|
||||
t.plan(1);
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/set-cookie/second-test/works`);
|
||||
xhr.withCredentials = true;
|
||||
xhr.onload = resolve;
|
||||
xhr.send();
|
||||
});
|
||||
xhr = new XMLHttpRequest();
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/print-cookie/second-test`);
|
||||
xhr.withCredentials = true;
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.responseText, 'works');
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
@ -0,0 +1,101 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { ProgressEvent } from '../progress-event';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest(),
|
||||
loadEvent: new ProgressEvent('load')
|
||||
}));
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
t.context.loadEvent = new ProgressEvent('load');
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget dispatchEvent works with a DOM0 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.onload = () => t.pass();
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget dispatchEvent works with a DOM2 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.addEventListener('load', () => t.pass());
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget dispatchEvent executes DOM2 listeners in order', t => {
|
||||
t.plan(1);
|
||||
let firstExecuted = false;
|
||||
t.context.xhr.addEventListener('load', () => firstExecuted = true);
|
||||
t.context.xhr.addEventListener('load', () => {
|
||||
if (firstExecuted) { t.pass(); }
|
||||
});
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget removes a DOM2 listener correctly', t => {
|
||||
t.plan(1);
|
||||
const listener = () => t.pass();
|
||||
t.context.xhr.addEventListener('load', listener);
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
t.context.xhr.removeEventListener('load', listener);
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget binds this correctly in a DOM0 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.onload = function () { if (this === t.context.xhr) { t.pass(); } };
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget binds this correctly in a DOM2 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.addEventListener('load', function () { if (this === t.context.xhr) { t.pass(); } });
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget sets target correctly in a DOM0 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.onload = function (event) { if (event.target === t.context.xhr) { t.pass(); } };
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget sets target correctly in a DOM2 listener', t => {
|
||||
t.plan(1);
|
||||
t.context.xhr.addEventListener('load', function (event) { if (event.target === t.context.xhr) { t.pass(); } });
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget works with a DOM0 and two DOM2 listeners', t => {
|
||||
t.plan(3);
|
||||
t.context.xhr.addEventListener('load', () => t.pass());
|
||||
t.context.xhr.onload = () => t.pass();
|
||||
t.context.xhr.addEventListener('load', () => t.pass());
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget does not invoke a DOM0 listener for a different event', t => {
|
||||
t.plan(0);
|
||||
['onerror', 'onloadstart', 'onprogress', 'onabort', 'ontimeout', 'onloadend']
|
||||
.forEach(eventType => t.context.xhr[eventType] = () => t.pass());
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
test('XMLHttpRequestEventTarget does not invoke a DOM2 listener for a different event', t => {
|
||||
t.plan(0);
|
||||
['error', 'loadstart', 'progress', 'abort', 'timeout', 'loadend']
|
||||
.forEach(eventType => t.context.xhr.addEventListener(eventType, () => t.pass()));
|
||||
t.context.xhr.dispatchEvent(t.context.loadEvent);
|
||||
});
|
||||
|
||||
// TODO:
|
||||
// * remove event listener from an event that had no listeners
|
||||
// * remove non-existent event listener from an event that had listeners
|
@ -0,0 +1,249 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest(),
|
||||
dripUrl: `http://localhost:${HttpServer.port}/_/drip`,
|
||||
dripJson: {drips: 3, size: 1000, ms: 50, length: true},
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
|
||||
XMLHttpRequest.nodejsSet({
|
||||
baseUrl: HttpServer.testUrl().replace('https://', 'http://')
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('level 2 events for a successful fetch with Content-Length set', async t => {
|
||||
let endFired = false;
|
||||
let intermediateProgressFired = false;
|
||||
const xhr = t.context.xhr;
|
||||
|
||||
await new Promise(resolve => {
|
||||
['loadstart', 'progress', 'load', 'loadend', 'error', 'abort'].forEach(addCheckedEvent);
|
||||
xhr.addEventListener('loadend', () => {
|
||||
endFired = true;
|
||||
resolve();
|
||||
});
|
||||
xhr.addEventListener('error', () => resolve());
|
||||
|
||||
xhr.open('POST', t.context.dripUrl);
|
||||
xhr.send(JSON.stringify(t.context.dripJson));
|
||||
});
|
||||
|
||||
t.true(intermediateProgressFired, 'at least one intermediate progress event was fired');
|
||||
|
||||
function addCheckedEvent(eventType: string) {
|
||||
xhr.addEventListener(eventType, event => {
|
||||
t.is(event.type, eventType, `event type is ${eventType}`);
|
||||
t.is(event.target, xhr, 'event has correct target');
|
||||
t.false(endFired, 'end is not fired');
|
||||
t.false(event.bubbles, 'event does not bubble');
|
||||
t.false(event.cancelable, 'event is not cancelable');
|
||||
|
||||
switch (eventType) {
|
||||
case 'loadstart':
|
||||
t.is(event.loaded, 0, 'on loadstart loaded = 0');
|
||||
t.false(event.lengthComputable, 'on loadstart length is not computable');
|
||||
t.is(event.total, 0, 'on loadstart event total is 0');
|
||||
break;
|
||||
case 'load':
|
||||
case 'loadend':
|
||||
t.is(event.loaded, 3000, 'on load/loadend loaded = 3000');
|
||||
t.true(event.lengthComputable, 'on load/loadend length is computable');
|
||||
t.is(event.total, 3000, 'on load/loadend event total is 0');
|
||||
break;
|
||||
case 'progress':
|
||||
t.true(event.loaded >= 0, 'on progress: loaded >= 0');
|
||||
t.true(event.loaded <= 3000, 'on progress: loaded <= 3000');
|
||||
if (event.lengthComputable) {
|
||||
t.is(event.total, 3000, 'on progress event when length is computable total is 3000');
|
||||
} else {
|
||||
t.is(event.total, 0, 'on progress event when length is not computable total is 0');
|
||||
}
|
||||
if (event.loaded > 0 && event.loaded < 3000) { intermediateProgressFired = true; }
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
test('level 2 events for a successful fetch without Content-Length set', async t => {
|
||||
let endFired = false;
|
||||
let intermediateProgressFired = false;
|
||||
const xhr = t.context.xhr;
|
||||
t.context.dripJson = {...t.context.dripJson, length: false};
|
||||
|
||||
await new Promise(resolve => {
|
||||
['loadstart', 'progress', 'load', 'loadend', 'error', 'abort'].forEach(addCheckedEvent);
|
||||
xhr.addEventListener('loadend', () => {
|
||||
endFired = true;
|
||||
resolve();
|
||||
});
|
||||
|
||||
xhr.open('POST', t.context.dripUrl);
|
||||
xhr.send(JSON.stringify(t.context.dripJson));
|
||||
});
|
||||
|
||||
t.true(intermediateProgressFired, 'at least one intermediate progress event was fired');
|
||||
|
||||
function addCheckedEvent(eventType: string) {
|
||||
xhr.addEventListener(eventType, event => {
|
||||
t.is(event.type, eventType, `event type is ${eventType}`);
|
||||
t.is(event.target, xhr, 'event has correct target');
|
||||
t.false(endFired, 'end is not fired');
|
||||
t.false(event.bubbles, 'event does not bubble');
|
||||
t.false(event.cancelable, 'event is not cancelable');
|
||||
t.false(event.lengthComputable, 'length is not computable');
|
||||
t.is(event.total, 0, 'when length is not computable total is 0');
|
||||
|
||||
switch (eventType) {
|
||||
case 'loadstart':
|
||||
t.is(event.loaded, 0, 'on loadstart loaded = 0');
|
||||
break;
|
||||
case 'load':
|
||||
case 'loadend':
|
||||
t.is(event.loaded, 3000, 'on load/loadend loaded = 3000');
|
||||
break;
|
||||
case 'progress':
|
||||
t.true(event.loaded >= 0, 'on progress: loaded >= 0');
|
||||
t.true(event.loaded <= 3000, 'on progress: loaded <= 3000');
|
||||
if (event.loaded > 0 && event.loaded < 3000) { intermediateProgressFired = true; }
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
test('level 2 events for a network error due to bad DNS', async t => {
|
||||
let errorFired = false;
|
||||
const xhr = t.context.xhr;
|
||||
|
||||
await new Promise(resolve => {
|
||||
['loadstart', 'progress', 'load', 'loadend', 'error', 'abort'].forEach(addCheckedEvent);
|
||||
xhr.addEventListener('loadend', () => resolve());
|
||||
|
||||
xhr.open('GET', 'https://broken.to.cause.an.xhrnetworkerror.com.a.com');
|
||||
xhr.send();
|
||||
});
|
||||
|
||||
t.true(errorFired, 'an error event was fired');
|
||||
|
||||
function addCheckedEvent(eventType: string) {
|
||||
xhr.addEventListener(eventType, () => {
|
||||
switch (eventType) {
|
||||
case 'load':
|
||||
case 'progress':
|
||||
t.fail();
|
||||
break;
|
||||
case 'error':
|
||||
errorFired = true;
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
test('readystatechange for a successful fetch with Content-Length set', async t => {
|
||||
let doneFired = false;
|
||||
const xhr = t.context.xhr;
|
||||
const states = [];
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('readystatechange', event => {
|
||||
t.is(event.type, 'readystatechange', 'event type is correct');
|
||||
t.false(doneFired, 'no readystatechange events after DONE');
|
||||
t.is(event.target, xhr, 'event has correct target');
|
||||
t.false(event.bubbles, 'event does not bubble');
|
||||
t.false(event.cancelable, 'event is not cancelable');
|
||||
|
||||
states.push((event.target as XMLHttpRequest).readyState);
|
||||
if ((event.target as XMLHttpRequest).readyState === XMLHttpRequest.DONE) {
|
||||
doneFired = true;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
xhr.open('POST', t.context.dripUrl);
|
||||
xhr.send(JSON.stringify(t.context.dripJson));
|
||||
});
|
||||
|
||||
t.deepEqual(states, [
|
||||
XMLHttpRequest.OPENED,
|
||||
XMLHttpRequest.HEADERS_RECEIVED,
|
||||
XMLHttpRequest.LOADING,
|
||||
XMLHttpRequest.DONE
|
||||
], 'right order of ready states');
|
||||
});
|
||||
|
||||
test('readystatechange for a successful fetch without Content-Length set', async t => {
|
||||
let doneFired = false;
|
||||
const xhr = t.context.xhr;
|
||||
const states = [];
|
||||
t.context.dripJson = {...t.context.dripJson, length: false};
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('readystatechange', event => {
|
||||
t.is(event.type, 'readystatechange', 'event type is correct');
|
||||
t.false(doneFired, 'no readystatechange events after DONE');
|
||||
t.is(event.target, xhr, 'event has correct target');
|
||||
t.false(event.bubbles, 'event does not bubble');
|
||||
t.false(event.cancelable, 'event is not cancelable');
|
||||
t.false(event.lengthComputable, 'length is not computable');
|
||||
t.is(event.total, 0, 'when length is not computable total is 0');
|
||||
|
||||
states.push((event.target as XMLHttpRequest).readyState);
|
||||
if ((event.target as XMLHttpRequest).readyState === XMLHttpRequest.DONE) {
|
||||
doneFired = true;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
xhr.open('POST', t.context.dripUrl);
|
||||
xhr.send(JSON.stringify(t.context.dripJson));
|
||||
});
|
||||
|
||||
t.deepEqual(states, [
|
||||
XMLHttpRequest.OPENED,
|
||||
XMLHttpRequest.HEADERS_RECEIVED,
|
||||
XMLHttpRequest.LOADING,
|
||||
XMLHttpRequest.DONE
|
||||
], 'right order of ready states');
|
||||
});
|
||||
|
||||
test('readystatechange for a network error due to bad DNS', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
const states = [];
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('readystatechange', event => {
|
||||
t.is(event.type, 'readystatechange', 'event type is correct');
|
||||
t.is(event.target, xhr, 'event has correct target');
|
||||
t.false(event.bubbles, 'event does not bubble');
|
||||
t.false(event.cancelable, 'event is not cancelable');
|
||||
|
||||
states.push((event.target as XMLHttpRequest).readyState);
|
||||
if ((event.target as XMLHttpRequest).readyState === XMLHttpRequest.DONE) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
xhr.open('GET', 'https://broken.to.cause.an.xhrnetworkerror.com.a.com');
|
||||
xhr.send();
|
||||
});
|
||||
|
||||
t.deepEqual(states, [
|
||||
XMLHttpRequest.OPENED,
|
||||
XMLHttpRequest.DONE
|
||||
], 'right order of ready states');
|
||||
});
|
BIN
local_modules/web3-providers-http/local_modules/xhr2-cookies/test/fixtures/hello.png
vendored
Normal file
BIN
local_modules/web3-providers-http/local_modules/xhr2-cookies/test/fixtures/hello.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 B |
@ -0,0 +1,189 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
|
||||
XMLHttpRequest.nodejsSet({
|
||||
baseUrl: HttpServer.testUrl().replace('https://', 'http://')
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('#setRequestHeader with allowed headers should send the headers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/headers`);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('X-Answer', '42');
|
||||
xhr.setRequestHeader('X-Header-Name', 'value');
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/, 'response text looks like JSON');
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.true(headers.hasOwnProperty('authorization'), 'headers have authorization header');
|
||||
t.is(headers.authorization, 'lol', 'authorization header is correct');
|
||||
t.true(headers.hasOwnProperty('x-answer'), 'headers have x-answer header');
|
||||
t.is(headers['x-answer'], '42', 'x-answer header is correct');
|
||||
t.true(headers.hasOwnProperty('x-header-name'), 'headers have x-header-name header');
|
||||
t.is(headers['x-header-name'], 'value', 'x-header-name header is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.send('');
|
||||
});
|
||||
});
|
||||
|
||||
test('#setRequestHeader with a mix of allowed and forbidden headers should only send the allowed headers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/headers`);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('Proxy-Authorization', 'evil:kitten');
|
||||
xhr.setRequestHeader('Sec-Breach', 'yes please');
|
||||
xhr.setRequestHeader('Host', 'www.google.com');
|
||||
xhr.setRequestHeader('Origin', 'https://www.google.com');
|
||||
xhr.setRequestHeader('X-Answer', '42');
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/, 'response text looks like JSON');
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.true(headers.hasOwnProperty('authorization'), 'headers have authorization header');
|
||||
t.is(headers['authorization'], 'lol', 'authorization header is correct');
|
||||
t.false(headers.hasOwnProperty('proxy-authorization'), 'headers do not have proxy-authorization header');
|
||||
t.false(headers.hasOwnProperty('sec-breach'), 'headers do not have sec-breach header');
|
||||
t.notRegex(headers['origin'] || '', /www\.google\.com/, 'header "origin" should not contain www.google.com');
|
||||
t.notRegex(headers['host'] || '', /www\.google\.com/, 'header "host" should not contain www.google.com');
|
||||
t.true(headers.hasOwnProperty('x-answer'), 'headers have x-answer header');
|
||||
t.is(headers['x-answer'], '42', 'x-answer header is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.send('');
|
||||
});
|
||||
});
|
||||
|
||||
test('#setRequestHeader with repeated headers should send all headers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/headers`);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
xhr.setRequestHeader('Authorization', 'troll');
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('X-Answer', '42');
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/, 'response text looks like JSON');
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.true(headers.hasOwnProperty('authorization'), 'headers have authorization header');
|
||||
t.is(headers['authorization'], 'troll, lol, lol', 'authorization header is correct');
|
||||
t.true(headers.hasOwnProperty('x-answer'), 'headers have x-answer header');
|
||||
t.is(headers['x-answer'], '42', 'x-answer header is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.send('');
|
||||
});
|
||||
});
|
||||
|
||||
test('#setRequestHeader with no headers should set the protected headers correctly', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/headers`);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
xhr.setRequestHeader('Authorization', 'troll');
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('Authorization', 'lol');
|
||||
xhr.setRequestHeader('X-Answer', '42');
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/, 'response text looks like JSON');
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.true(headers.hasOwnProperty('connection'), 'headers have connection header');
|
||||
t.is(headers['connection'], 'keep-alive', 'connection header is correct');
|
||||
t.true(headers.hasOwnProperty('host'), 'headers have host header');
|
||||
t.is(headers['host'], `localhost:${HttpServer.port}`, 'host header is correct');
|
||||
t.true(headers.hasOwnProperty('user-agent'), 'headers have user-agent header');
|
||||
t.regex(headers['user-agent'], /^Mozilla\//, 'user-agent header is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.send('');
|
||||
});
|
||||
});
|
||||
|
||||
test('#getResponseHeader returns accessible headers, returns null for private headers, has headers on HEADERS_RECEIVED readyState', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/get-headers`);
|
||||
const headerJson = `{
|
||||
"Accept-Ranges": "bytes",
|
||||
"Content-Type": "application/xhr2; charset=utf-1337",
|
||||
"Set-Cookie": "UserID=JohnDoe; Max-Age=3600; Version=1",
|
||||
"X-Header": "one, more, value"
|
||||
}`;
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onloadend = () => {
|
||||
t.is(xhr.getResponseHeader('AccEPt-RANgeS'), 'bytes', 'AccEPt-RANgeS works correctly');
|
||||
t.is(xhr.getResponseHeader('content-Type'), 'application/xhr2; charset=utf-1337', 'content-Type works correctly');
|
||||
t.is(xhr.getResponseHeader('X-Header'), 'one, more, value', 'X-Header works correctly');
|
||||
t.is(xhr.getResponseHeader('set-cookie'), null, 'set-cookie works correctly');
|
||||
resolve();
|
||||
};
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState !== XMLHttpRequest.HEADERS_RECEIVED) { return; }
|
||||
t.is(xhr.getResponseHeader('AccEPt-RANgeS'), 'bytes', 'AccEPt-RANgeS works correctly when HEADERS_RECEIVED ready state');
|
||||
};
|
||||
xhr.send(headerJson);
|
||||
});
|
||||
});
|
||||
|
||||
test('#getAllResponseHeaders contains accessible headers, does not contain private headers, has headers on HEADERS_RECEIVED readyState', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/get-headers`);
|
||||
const headerJson = `{
|
||||
"Accept-Ranges": "bytes",
|
||||
"Content-Type": "application/xhr2; charset=utf-1337",
|
||||
"Set-Cookie": "UserID=JohnDoe; Max-Age=3600; Version=1",
|
||||
"X-Header": "one, more, value"
|
||||
}`;
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.onloadend = () => {
|
||||
const headers = xhr.getAllResponseHeaders();
|
||||
t.regex(headers, /(\A|\r\n)accept-ranges: bytes(\r\n|\Z)/mi);
|
||||
t.regex(headers, /(\A|\r\n)content-type: application\/xhr2; charset=utf-1337(\r\n|\Z)/mi);
|
||||
t.regex(headers, /(\A|\r\n)X-Header: one, more, value(\r\n|\Z)/mi);
|
||||
t.notRegex(headers, /(\A|\r\n)set-cookie:/mi);
|
||||
resolve();
|
||||
};
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState !== XMLHttpRequest.HEADERS_RECEIVED) { return; }
|
||||
const headers = xhr.getAllResponseHeaders();
|
||||
t.regex(headers, /(\A|\r\n)accept-ranges: bytes(\r\n|\Z)/mi);
|
||||
};
|
||||
xhr.send(headerJson);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO:
|
||||
// * set request header after request opened should throw InvalidStateError
|
||||
// *
|
@ -0,0 +1,50 @@
|
||||
export const certificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIDXjCCAkYCCQCgZ4DViKxZtTANBgkqhkiG9w0BAQsFADBxMQswCQYDVQQGEwJS
|
||||
TzELMAkGA1UECAwCVE0xCzAJBgNVBAcMAlhYMQwwCgYDVQQKDANYWFgxDTALBgNV
|
||||
BAsMBFhYWFgxEjAQBgNVBAMMCWxvY2FsaG9zdDEXMBUGCSqGSIb3DQEJARYIWEBY
|
||||
WC5YWFgwHhcNMTcxMTEzMTQzMTE2WhcNMjAwOTAyMTQzMTE2WjBxMQswCQYDVQQG
|
||||
EwJSTzELMAkGA1UECAwCVE0xCzAJBgNVBAcMAlhYMQwwCgYDVQQKDANYWFgxDTAL
|
||||
BgNVBAsMBFhYWFgxEjAQBgNVBAMMCWxvY2FsaG9zdDEXMBUGCSqGSIb3DQEJARYI
|
||||
WEBYWC5YWFgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyJ+21siOW
|
||||
oRkgVSpQMaUAw/R54GG98k9IEMQnGBoD7HlnX4avgz0fNaA/xNdQuKVZqR0oshCx
|
||||
6ks6mX4z/nYHh4SNmQVmAH7mJnT5aqHVs4OplVU5ZmZNsBx7+7JEFk64G7k011rI
|
||||
76MVjLrNYJSTlgrtYOcNJle6awCwmI2nsrHSJJeyMVOGUK8H9RDzsPPZIQS0u4wJ
|
||||
P8mIAoln/mpgP5I2lNTM2FaokmQq4mEYErUsWf+DhSlmnbZFxt5V3r/xHWVrouig
|
||||
RsjhFxoGRg3p0HoUR79Rc8LqbbMtibh1qSkXcHjue1rBcSYurQNPzdbf3R4WuUyb
|
||||
lxhui0rfu8fFAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABphKcUJbdEhUpWF4EZE
|
||||
BBl/uzE4/WXtQZdgz3fGpvpzmXZBRtbkdPR3jxBW1c9asCfb366dXRb8im6/p6ae
|
||||
sAxZINMKIQ8KCIEb+StVMc4MvxASMm1SSz/kFuTCA2Q8vD5sHJrFcoKk6HKNEOLu
|
||||
dALKpO8ZDuxjv036sCnjfyDue9psSccsLuAhfr2NLL5Ky9lWrJFi3b35D5UHrlK/
|
||||
9mb9izRgZSC9+sZgpSyvIK6idKoWB4s9RpCn8itucFHHUDOvv8DdwvsF/5iVyWz7
|
||||
R5uR4/qA8k7lbHHLosu2ELyx3N6Go0AskjxzsONPOKNlGIDllTx21mkIvTkGlJgs
|
||||
8/4=
|
||||
-----END CERTIFICATE-----
|
||||
`;
|
||||
export const key = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAsifttbIjlqEZIFUqUDGlAMP0eeBhvfJPSBDEJxgaA+x5Z1+G
|
||||
r4M9HzWgP8TXULilWakdKLIQsepLOpl+M/52B4eEjZkFZgB+5iZ0+Wqh1bODqZVV
|
||||
OWZmTbAce/uyRBZOuBu5NNdayO+jFYy6zWCUk5YK7WDnDSZXumsAsJiNp7Kx0iSX
|
||||
sjFThlCvB/UQ87Dz2SEEtLuMCT/JiAKJZ/5qYD+SNpTUzNhWqJJkKuJhGBK1LFn/
|
||||
g4UpZp22RcbeVd6/8R1la6LooEbI4RcaBkYN6dB6FEe/UXPC6m2zLYm4dakpF3B4
|
||||
7ntawXEmLq0DT83W390eFrlMm5cYbotK37vHxQIDAQABAoIBAEUu8EbA2MUj5kgC
|
||||
Cp59yN/VONkjY5GJyXPo3uN3npKrgDG+jOUXh+LYxlQ9MogsTDnXTHWDQKx2maQ1
|
||||
+yZhyJ//5l++brQ/uQfTI1XALPx568UtMp1JwKymmUkkYwPBzev9CB0XDDA/rwst
|
||||
TVV4DfqKJ9Aq807N9v9zkh8B/vCB9Ecvfco7Q2+AgrsLoaUDR9IwbiQXLqrqLA/F
|
||||
tXh29Okwt7A3cv2C7Yd0rWyZLJi5iyH/lzcu33xGfaIAeN0fHtefKEhPU/yS69VM
|
||||
9HbdDC44h0/psNyBt0dlrUYx32oYzF8EV4brrqcZTVUJNfCEqA16nTMKSmCJQdR8
|
||||
nPJCRYECgYEA3U/0MyNDVa/OphEcBGLnXhRBeBGTGIP768gkn0Fw3Fgk1v6eqfKb
|
||||
JqBujdgJjxbebo32OZeRLw92RBsfNY5IyIwVUKgZbtNkysgf612IhNoeBF7Ljz3r
|
||||
BbSq3gwOHuUszCjO8/SjQn9bRLxVifrRD04SdHudMN4V2g98yoBBEdUCgYEAzhRZ
|
||||
BWdOlLG2gAa8waPeuHUkwGU4zKly3zLSnbNvJJJ/wSTbuGmPQhLcWXq27gepHzZf
|
||||
fvVJbpHrLHksh3fwdPusmygXD/s0gxMQJqJJledk1GEUnPjuuAImKvmeJWyX5lGq
|
||||
APMh+M5ZB6CBu1dqapAs7nkOLCsSDGatRwc65jECgYBGI2q/MjPK2jbhxpZchYPR
|
||||
+xVsmhVGNb4HUZzZpAHCs2SphnR+Y9br/PhMl+Ufph3EZ9VbFz/57CqNFxNjA77p
|
||||
YAv5Te0RhIlzAs2q6C+1+vJ8bBaTRQpQ+psUWDm5bOQvp9c+1Y9QKdChDhcF7amH
|
||||
8jRDGlINBLVkMHhaLR9yKQKBgQDIBfH+D66zHucPzvpJTYAxM+qvH9CIvfP0doT9
|
||||
cptvOQ7tbpQho7vcGyhrZXPHCAJ8fC8msHhM7S8B5L924dCwC1QW6UuxRFdM3iTw
|
||||
Ctc3u/gfN/dlAS3bxqI7VjvNAWFSuXM0JsmTkN3TTFR/fTKaKkSiVzeNYWTMSqDn
|
||||
bzoZEQKBgFZcAbn2h86jYJ2tcznBriLI8rZBkPL9MFP4QM2Ksz5/8fsJ84EPsatg
|
||||
700S1yasmDwaOgBLtSKsy7Rju5E3nebaPgLw3x92LiI07F97p2Y5ftSbRgslaih4
|
||||
fDBm/C82anx0q9s4psw1oNnYj20c+imPIWvM7A0W85kmqcmQvzwZ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`;
|
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
rm localhost.key.pem localhost.cert.pem
|
||||
openssl req -nodes -newkey rsa:2048 -keyout localhost.key2.pem -x509 -days 1024 -out localhost.cert.pem
|
||||
openssl rsa -in localhost.key2.pem -out localhost.key.pem
|
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXjCCAkYCCQCgZ4DViKxZtTANBgkqhkiG9w0BAQsFADBxMQswCQYDVQQGEwJS
|
||||
TzELMAkGA1UECAwCVE0xCzAJBgNVBAcMAlhYMQwwCgYDVQQKDANYWFgxDTALBgNV
|
||||
BAsMBFhYWFgxEjAQBgNVBAMMCWxvY2FsaG9zdDEXMBUGCSqGSIb3DQEJARYIWEBY
|
||||
WC5YWFgwHhcNMTcxMTEzMTQzMTE2WhcNMjAwOTAyMTQzMTE2WjBxMQswCQYDVQQG
|
||||
EwJSTzELMAkGA1UECAwCVE0xCzAJBgNVBAcMAlhYMQwwCgYDVQQKDANYWFgxDTAL
|
||||
BgNVBAsMBFhYWFgxEjAQBgNVBAMMCWxvY2FsaG9zdDEXMBUGCSqGSIb3DQEJARYI
|
||||
WEBYWC5YWFgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyJ+21siOW
|
||||
oRkgVSpQMaUAw/R54GG98k9IEMQnGBoD7HlnX4avgz0fNaA/xNdQuKVZqR0oshCx
|
||||
6ks6mX4z/nYHh4SNmQVmAH7mJnT5aqHVs4OplVU5ZmZNsBx7+7JEFk64G7k011rI
|
||||
76MVjLrNYJSTlgrtYOcNJle6awCwmI2nsrHSJJeyMVOGUK8H9RDzsPPZIQS0u4wJ
|
||||
P8mIAoln/mpgP5I2lNTM2FaokmQq4mEYErUsWf+DhSlmnbZFxt5V3r/xHWVrouig
|
||||
RsjhFxoGRg3p0HoUR79Rc8LqbbMtibh1qSkXcHjue1rBcSYurQNPzdbf3R4WuUyb
|
||||
lxhui0rfu8fFAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABphKcUJbdEhUpWF4EZE
|
||||
BBl/uzE4/WXtQZdgz3fGpvpzmXZBRtbkdPR3jxBW1c9asCfb366dXRb8im6/p6ae
|
||||
sAxZINMKIQ8KCIEb+StVMc4MvxASMm1SSz/kFuTCA2Q8vD5sHJrFcoKk6HKNEOLu
|
||||
dALKpO8ZDuxjv036sCnjfyDue9psSccsLuAhfr2NLL5Ky9lWrJFi3b35D5UHrlK/
|
||||
9mb9izRgZSC9+sZgpSyvIK6idKoWB4s9RpCn8itucFHHUDOvv8DdwvsF/5iVyWz7
|
||||
R5uR4/qA8k7lbHHLosu2ELyx3N6Go0AskjxzsONPOKNlGIDllTx21mkIvTkGlJgs
|
||||
8/4=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAsifttbIjlqEZIFUqUDGlAMP0eeBhvfJPSBDEJxgaA+x5Z1+G
|
||||
r4M9HzWgP8TXULilWakdKLIQsepLOpl+M/52B4eEjZkFZgB+5iZ0+Wqh1bODqZVV
|
||||
OWZmTbAce/uyRBZOuBu5NNdayO+jFYy6zWCUk5YK7WDnDSZXumsAsJiNp7Kx0iSX
|
||||
sjFThlCvB/UQ87Dz2SEEtLuMCT/JiAKJZ/5qYD+SNpTUzNhWqJJkKuJhGBK1LFn/
|
||||
g4UpZp22RcbeVd6/8R1la6LooEbI4RcaBkYN6dB6FEe/UXPC6m2zLYm4dakpF3B4
|
||||
7ntawXEmLq0DT83W390eFrlMm5cYbotK37vHxQIDAQABAoIBAEUu8EbA2MUj5kgC
|
||||
Cp59yN/VONkjY5GJyXPo3uN3npKrgDG+jOUXh+LYxlQ9MogsTDnXTHWDQKx2maQ1
|
||||
+yZhyJ//5l++brQ/uQfTI1XALPx568UtMp1JwKymmUkkYwPBzev9CB0XDDA/rwst
|
||||
TVV4DfqKJ9Aq807N9v9zkh8B/vCB9Ecvfco7Q2+AgrsLoaUDR9IwbiQXLqrqLA/F
|
||||
tXh29Okwt7A3cv2C7Yd0rWyZLJi5iyH/lzcu33xGfaIAeN0fHtefKEhPU/yS69VM
|
||||
9HbdDC44h0/psNyBt0dlrUYx32oYzF8EV4brrqcZTVUJNfCEqA16nTMKSmCJQdR8
|
||||
nPJCRYECgYEA3U/0MyNDVa/OphEcBGLnXhRBeBGTGIP768gkn0Fw3Fgk1v6eqfKb
|
||||
JqBujdgJjxbebo32OZeRLw92RBsfNY5IyIwVUKgZbtNkysgf612IhNoeBF7Ljz3r
|
||||
BbSq3gwOHuUszCjO8/SjQn9bRLxVifrRD04SdHudMN4V2g98yoBBEdUCgYEAzhRZ
|
||||
BWdOlLG2gAa8waPeuHUkwGU4zKly3zLSnbNvJJJ/wSTbuGmPQhLcWXq27gepHzZf
|
||||
fvVJbpHrLHksh3fwdPusmygXD/s0gxMQJqJJledk1GEUnPjuuAImKvmeJWyX5lGq
|
||||
APMh+M5ZB6CBu1dqapAs7nkOLCsSDGatRwc65jECgYBGI2q/MjPK2jbhxpZchYPR
|
||||
+xVsmhVGNb4HUZzZpAHCs2SphnR+Y9br/PhMl+Ufph3EZ9VbFz/57CqNFxNjA77p
|
||||
YAv5Te0RhIlzAs2q6C+1+vJ8bBaTRQpQ+psUWDm5bOQvp9c+1Y9QKdChDhcF7amH
|
||||
8jRDGlINBLVkMHhaLR9yKQKBgQDIBfH+D66zHucPzvpJTYAxM+qvH9CIvfP0doT9
|
||||
cptvOQ7tbpQho7vcGyhrZXPHCAJ8fC8msHhM7S8B5L924dCwC1QW6UuxRFdM3iTw
|
||||
Ctc3u/gfN/dlAS3bxqI7VjvNAWFSuXM0JsmTkN3TTFR/fTKaKkSiVzeNYWTMSqDn
|
||||
bzoZEQKBgFZcAbn2h86jYJ2tcznBriLI8rZBkPL9MFP4QM2Ksz5/8fsJ84EPsatg
|
||||
700S1yasmDwaOgBLtSKsy7Rju5E3nebaPgLw3x92LiI07F97p2Y5ftSbRgslaih4
|
||||
fDBm/C82anx0q9s4psw1oNnYj20c+imPIWvM7A0W85kmqcmQvzwZ
|
||||
-----END RSA PRIVATE KEY-----
|
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyJ+21siOWoRkg
|
||||
VSpQMaUAw/R54GG98k9IEMQnGBoD7HlnX4avgz0fNaA/xNdQuKVZqR0oshCx6ks6
|
||||
mX4z/nYHh4SNmQVmAH7mJnT5aqHVs4OplVU5ZmZNsBx7+7JEFk64G7k011rI76MV
|
||||
jLrNYJSTlgrtYOcNJle6awCwmI2nsrHSJJeyMVOGUK8H9RDzsPPZIQS0u4wJP8mI
|
||||
Aoln/mpgP5I2lNTM2FaokmQq4mEYErUsWf+DhSlmnbZFxt5V3r/xHWVrouigRsjh
|
||||
FxoGRg3p0HoUR79Rc8LqbbMtibh1qSkXcHjue1rBcSYurQNPzdbf3R4WuUyblxhu
|
||||
i0rfu8fFAgMBAAECggEARS7wRsDYxSPmSAIKnn3I39U42SNjkYnJc+je43eekquA
|
||||
Mb6M5ReH4tjGVD0yiCxMOddMdYNArHaZpDX7JmHIn//mX75utD+5B9MjVcAs/Hnr
|
||||
xS0ynUnArKaZSSRjA8HN6/0IHRcMMD+vCy1NVXgN+oon0CrzTs32/3OSHwH+8IH0
|
||||
Ry99yjtDb4CCuwuhpQNH0jBuJBcuquosD8W1eHb06TC3sDdy/YLth3StbJksmLmL
|
||||
If+XNy7ffEZ9ogB43R8e158oSE9T/JLr1Uz0dt0MLjiHT+mw3IG3R2WtRjHfahjM
|
||||
XwRXhuuupxlNVQk18ISoDXqdMwpKYIlB1Hyc8kJFgQKBgQDdT/QzI0NVr86mERwE
|
||||
YudeFEF4EZMYg/vryCSfQXDcWCTW/p6p8psmoG6N2AmPFt5ujfY5l5EvD3ZEGx81
|
||||
jkjIjBVQqBlu02TKyB/rXYiE2h4EXsuPPesFtKreDA4e5SzMKM7z9KNCf1tEvFWJ
|
||||
+tEPThJ0e50w3hXaD3zKgEER1QKBgQDOFFkFZ06UsbaABrzBo964dSTAZTjMqXLf
|
||||
MtKds28kkn/BJNu4aY9CEtxZerbuB6kfNl9+9UlukesseSyHd/B0+6ybKBcP+zSD
|
||||
ExAmokmV52TUYRSc+O64AiYq+Z4lbJfmUaoA8yH4zlkHoIG7V2pqkCzueQ4sKxIM
|
||||
Zq1HBzrmMQKBgEYjar8yM8raNuHGllyFg9H7FWyaFUY1vgdRnNmkAcKzZKmGdH5j
|
||||
1uv8+EyX5R+mHcRn1VsXP/nsKo0XE2MDvulgC/lN7RGEiXMCzaroL7X68nxsFpNF
|
||||
ClD6mxRYObls5C+n1z7Vj1Ap0KEOFwXtqYfyNEMaUg0EtWQweFotH3IpAoGBAMgF
|
||||
8f4PrrMe5w/O+klNgDEz6q8f0Ii98/R2hP1ym285Du1ulCGju9wbKGtlc8cIAnx8
|
||||
LyaweEztLwHkv3bh0LALVBbpS7FEV0zeJPAK1ze7+B8392UBLdvGojtWO80BYVK5
|
||||
czQmyZOQ3dNMVH99MpoqRKJXN41hZMxKoOdvOhkRAoGAVlwBufaHzqNgna1zOcGu
|
||||
IsjytkGQ8v0wU/hAzYqzPn/x+wnzgQ+xq2DvTRLXJqyYPBo6AEu1IqzLtGO7kTed
|
||||
5to+AvDfH3YuIjTsX3unZjl+1JtGCyVqKHh8MGb8LzZqfHSr2zimzDWg2diPbRz6
|
||||
KY8ha8zsDRbzmSapyZC/PBk=
|
||||
-----END PRIVATE KEY-----
|
@ -0,0 +1,8 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const PNGBuffer = fs.readFileSync(path.join(__dirname, '../fixtures/hello.png'));
|
||||
const PNGUint8Array = new Uint8Array(PNGBuffer);
|
||||
const PNGArrayBuffer = PNGUint8Array.buffer as ArrayBuffer;
|
||||
|
||||
export { PNGBuffer, PNGArrayBuffer, PNGUint8Array };
|
@ -0,0 +1,228 @@
|
||||
import * as express from 'express';
|
||||
import { Application, NextFunction, Request, Response } from 'express';
|
||||
import * as http from 'http';
|
||||
import { Server as HttpServer } from 'http';
|
||||
import * as https from 'https';
|
||||
import { Server as HttpsServer } from 'https';
|
||||
import * as bodyParser from 'body-parser';
|
||||
import * as cookieParser from 'cookie-parser';
|
||||
import { certificate, key } from './certificates/certificate';
|
||||
import * as path from 'path';
|
||||
|
||||
export class XhrServer {
|
||||
app: Application;
|
||||
server: HttpServer | HttpsServer;
|
||||
serverStarted: Promise<void>;
|
||||
|
||||
private setServerStarted: () => void;
|
||||
|
||||
constructor(public port = 8080, private useHttps = false) {
|
||||
this.serverStarted = new Promise(resolve => this.setServerStarted = resolve);
|
||||
this.createApp();
|
||||
}
|
||||
|
||||
testUrl() {
|
||||
return `https://localhost:${this.port}/test/html/browser_test.html`;
|
||||
}
|
||||
|
||||
sslCertificate() {
|
||||
return this.useHttps ? certificate : null;
|
||||
}
|
||||
|
||||
sslKey() {
|
||||
return this.useHttps ? key : null;
|
||||
}
|
||||
|
||||
createApp() {
|
||||
this.app = express();
|
||||
this.app.use(bodyParser.json());
|
||||
this.app.use(bodyParser.urlencoded({ extended: true }));
|
||||
this.app.use(cookieParser());
|
||||
|
||||
this.app.use((request: Request, response: Response, next: NextFunction) => {
|
||||
response.header('Access-Control-Allow-Origin', '*');
|
||||
response.header('Access-Control-Allow-Methods', 'DELETE,GET,POST,PUT');
|
||||
response.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Cookie');
|
||||
next();
|
||||
});
|
||||
|
||||
this.app.get('/test/fixtures/hello.txt', (request: Request, response: Response) => {
|
||||
const body = 'Hello, world!';
|
||||
response.header('Content-Type', 'text/plain; charset=utf-8');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
this.app.get('/test/fixtures/hello.json', (request: Request, response: Response) => {
|
||||
const body = '{"hello": "world", "answer": 42}\n';
|
||||
response.header('Content-Type', 'application/json');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
this.app.get('/test/html/browser_test.html', (request: Request, response: Response) => {
|
||||
const body = '<p>Test</p>';
|
||||
response.header('Content-Type', 'text/html');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
this.app.all('/_/method', (request: Request, response: Response) => {
|
||||
const body = request.method;
|
||||
response.header('Content-Type', 'text/plain; charset=utf-8');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
// Echoes the request body. Used to test send(data).
|
||||
this.app.post('/_/echo', (request: Request, response: Response) => {
|
||||
if (request.headers['content-type']) {
|
||||
response.header('Content-Type', request.headers['content-type']);
|
||||
}
|
||||
if (request.headers['content-length']) {
|
||||
response.header('Content-Length', request.headers['content-length']);
|
||||
}
|
||||
request.on('data', chunk => response.write(chunk));
|
||||
request.on('end', () => response.end());
|
||||
});
|
||||
|
||||
// Lists the request headers. Used to test setRequestHeader().
|
||||
this.app.all('/_/headers', (request: Request, response: Response) => {
|
||||
const body = JSON.stringify(request.headers);
|
||||
response.header('Content-Type', 'application/json');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
// Sets the response headers in the request. Used to test getResponse*().
|
||||
this.app.post('/_/get-headers', (request: Request, response: Response) => {
|
||||
let jsonString = '';
|
||||
request.on('data', chunk => jsonString += chunk);
|
||||
request.on('end', () => {
|
||||
const headers = JSON.parse(jsonString);
|
||||
for (let name in headers) {
|
||||
if (headers.hasOwnProperty(name)) {
|
||||
response.header(name, headers[name]);
|
||||
}
|
||||
}
|
||||
response.header('Content-Length', '0');
|
||||
response.end('');
|
||||
});
|
||||
});
|
||||
|
||||
// Sets every response detail. Used for error testing.
|
||||
this.app.post('/_/response', (request: Request, response: Response) => {
|
||||
let jsonString = '';
|
||||
request.on('data', chunk => jsonString += chunk);
|
||||
request.on('end', () => {
|
||||
const json = JSON.parse(jsonString);
|
||||
response.writeHead(json.code, json.status, json.headers);
|
||||
if (json.body) { response.write(json.body); }
|
||||
response.end();
|
||||
});
|
||||
});
|
||||
|
||||
// Sends data in small chunks. Used for event testing.
|
||||
this.app.post('/_/drip', (request: Request, response: Response) => {
|
||||
request.connection.setNoDelay();
|
||||
let jsonString = '';
|
||||
request.on('data', chunk => jsonString += chunk);
|
||||
request.on('end', () => {
|
||||
const json = JSON.parse(jsonString);
|
||||
let sentDrips = 0;
|
||||
const drip = new Array(json.size + 1).join('.');
|
||||
response.header('Content-Type', 'text/plain');
|
||||
if (json.length) { response.header('Content-Length', (json.drips * json.size).toString()); }
|
||||
|
||||
(function sendDrip() {
|
||||
response.write(drip);
|
||||
sentDrips++;
|
||||
if (sentDrips >= json.drips) { return response.end(); }
|
||||
setTimeout(sendDrip, json.ms);
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
// Returns a HTTP redirect. Used to test the redirection handling code.
|
||||
this.app.all('/_/redirect/:status/:next', (request: Request, response: Response) => {
|
||||
response.statusCode = +request.params.status;
|
||||
response.header('Location', `${request.protocol}://${request.get('host')}/_/${request.params.next}`);
|
||||
const body = '<p>This is supposed to have a redirect link</p>';
|
||||
response.header('Content-Type', 'text/html');
|
||||
response.header('Content-Length', body.length.toString());
|
||||
response.header('X-Redirect-Header', 'should not show up');
|
||||
response.end(body);
|
||||
});
|
||||
|
||||
// Sets a cookie
|
||||
this.app.all('/_/set-cookie/:name/:value', (request: Request, response: Response) => {
|
||||
response.cookie(request.params.name, request.params.value);
|
||||
response.header('Content-Type', 'text/plain');
|
||||
response.header('Content-Length', '0');
|
||||
response.end();
|
||||
});
|
||||
|
||||
// Redirects and sets a cookie.
|
||||
this.app.all('/_/redirect-cookie/:name/:value', (request: Request, response: Response) => {
|
||||
response.cookie(request.params.name, request.params.value);
|
||||
response.redirect(301,
|
||||
`${request.protocol}://${request.get('host')}/_/print-cookie/${request.params.name}`
|
||||
);
|
||||
});
|
||||
|
||||
// Read cookie + print its value.
|
||||
this.app.get('/_/print-cookie/:name', (request: Request, response: Response) => {
|
||||
const cookieValue = request.cookies[request.params.name];
|
||||
response.header('Content-Type', 'text/plain');
|
||||
response.header('Content-Length', cookieValue.length.toString());
|
||||
response.end(cookieValue);
|
||||
});
|
||||
|
||||
// Requested when the browser test suite completes.
|
||||
this.app.get('/_/end', (request: Request, response: Response) => {
|
||||
const failed = request.query.hasOwnProperty('failed') ? +request.query.failed : 1;
|
||||
const total = request.query.hasOwnProperty('total') ? +request.query.total : 0;
|
||||
const passed = total - failed;
|
||||
const exitCode = failed ? 1 : 0;
|
||||
console.log(`${passed} passed, ${failed} failed`);
|
||||
|
||||
response.header('Content-Type', 'image/png');
|
||||
response.header('Content-Length', '0');
|
||||
response.end('');
|
||||
|
||||
if (!process.env.hasOwnProperty('NO_EXIT')) {
|
||||
this.server.close();
|
||||
process.exit(exitCode);
|
||||
}
|
||||
});
|
||||
|
||||
this.app.use(express.static(path.join(__dirname, '../../')));
|
||||
|
||||
this.createServer();
|
||||
}
|
||||
|
||||
createServer() {
|
||||
this.server = this.useHttps
|
||||
? https.createServer({
|
||||
cert: this.sslCertificate(),
|
||||
key: this.sslKey()
|
||||
}, this.app)
|
||||
: http.createServer(this.app);
|
||||
|
||||
this.server.on('error', (error) => {
|
||||
if (error.code !== 'EADDRINUSE') { return; }
|
||||
this.port += 2;
|
||||
this.createServer();
|
||||
});
|
||||
this.server.on('listening', () => {
|
||||
this.setServerStarted();
|
||||
});
|
||||
|
||||
this.server.listen(this.port);
|
||||
}
|
||||
}
|
||||
|
||||
const HttpServer = new XhrServer(8900, false);
|
||||
const HttpsServer = new XhrServer(8901, true);
|
||||
|
||||
export { HttpServer, HttpsServer };
|
@ -0,0 +1,120 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest(),
|
||||
customXhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
t.context.customXhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('XMLHttpRequest.nodejsSet with a httpAgent option', t => {
|
||||
const customAgent = {custom: 'httpAgent'};
|
||||
const defaultAgent = XMLHttpRequest.prototype.nodejsHttpAgent;
|
||||
const agent = {mocking: 'httpAgent'};
|
||||
t.context.customXhr.nodejsHttpAgent = customAgent as any;
|
||||
XMLHttpRequest.nodejsSet({httpAgent: agent} as any);
|
||||
t.is(t.context.xhr.nodejsHttpAgent, agent as any, 'sets the default nodejsHttpAgent');
|
||||
t.is(t.context.customXhr.nodejsHttpAgent, customAgent as any, 'does not interfere with custom nodejsHttpAgent settings');
|
||||
XMLHttpRequest.nodejsSet({httpAgent: defaultAgent});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest.nodejsSet with a httpsAgent option', t => {
|
||||
const customAgent = {custom: 'httpsAgent'};
|
||||
const defaultAgent = XMLHttpRequest.prototype.nodejsHttpsAgent;
|
||||
const agent = {mocking: 'httpsAgent'};
|
||||
t.context.customXhr.nodejsHttpsAgent = customAgent as any;
|
||||
XMLHttpRequest.nodejsSet({httpsAgent: agent} as any);
|
||||
t.is(t.context.xhr.nodejsHttpsAgent, agent as any, 'sets the default nodejsHttpsAgent');
|
||||
t.is(t.context.customXhr.nodejsHttpsAgent, customAgent as any, 'does not interfere with custom nodejsHttpsAgent settings');
|
||||
XMLHttpRequest.nodejsSet({httpsAgent: defaultAgent});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest.nodejsSet with a baseUrl option', t => {
|
||||
const customBaseUrl = 'http://custom.url/base';
|
||||
const defaultBaseUrl = XMLHttpRequest.prototype.nodejsBaseUrl;
|
||||
const baseUrl = 'http://localhost/base';
|
||||
t.context.customXhr.nodejsBaseUrl = customBaseUrl;
|
||||
XMLHttpRequest.nodejsSet({baseUrl});
|
||||
t.is(t.context.xhr.nodejsBaseUrl, baseUrl, 'sets the default nodejsBaseUrl');
|
||||
t.is(t.context.customXhr.nodejsBaseUrl, customBaseUrl, 'does not interfere with custom nodejsBaseUrl settings');
|
||||
XMLHttpRequest.nodejsSet({baseUrl: defaultBaseUrl});
|
||||
});
|
||||
|
||||
test('#nodejsSet with a httpAgent option', t => {
|
||||
const customAgent = {custom: 'httpAgent'};
|
||||
t.context.customXhr.nodejsSet({httpAgent: customAgent as any});
|
||||
t.is(t.context.customXhr.nodejsHttpAgent, customAgent as any, 'sets nodejsHttpAgent on the XHR instance');
|
||||
t.not(t.context.xhr.nodejsHttpAgent, customAgent as any, 'does not interfere with default nodejsHttpAgent settings');
|
||||
});
|
||||
|
||||
test('#nodejsSet with a httpsAgent option', t => {
|
||||
const customAgent = {custom: 'httpsAgent'};
|
||||
t.context.customXhr.nodejsSet({httpsAgent: customAgent as any});
|
||||
t.is(t.context.customXhr.nodejsHttpsAgent, customAgent as any, 'sets nodejsHttpsAgent on the XHR instance');
|
||||
t.not(t.context.xhr.nodejsHttpsAgent, customAgent as any, 'does not interfere with default nodejsHttpsAgent settings');
|
||||
});
|
||||
|
||||
test('base URL parsing with null baseUrl', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: null});
|
||||
const parsedUrl = xhr._parseUrl('http://www.domain.com/path');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'http://www.domain.com/path');
|
||||
});
|
||||
|
||||
test('base URL parsing with a (protocol, domain, filePath) baseUrl parses an absolute URL', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: 'https://base.url/dir/file.html'});
|
||||
const parsedUrl = xhr._parseUrl('http://www.domain.com/path');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'http://www.domain.com/path');
|
||||
});
|
||||
|
||||
test('base URL parsing with a (protocol, domain, filePath) baseUrl parses a path-relative URL', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: 'https://base.url/dir/file.html'});
|
||||
const parsedUrl = xhr._parseUrl('path/to.js');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'https://base.url/dir/path/to.js');
|
||||
});
|
||||
|
||||
test('base URL parsing with a (protocol, domain, filePath) baseUrl parses a path-relative URL with ..', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: 'https://base.url/dir/file.html'});
|
||||
const parsedUrl = xhr._parseUrl('../path/to.js');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'https://base.url/path/to.js');
|
||||
});
|
||||
|
||||
test('base URL parsing with a (protocol, domain, filePath) baseUrl parses a host-relative URL', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: 'https://base.url/dir/file.html'});
|
||||
const parsedUrl = xhr._parseUrl('/path/to.js');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'https://base.url/path/to.js');
|
||||
});
|
||||
|
||||
test('base URL parsing with a (protocol, domain, filePath) baseUrl parses a protocol-relative URL', t => {
|
||||
const xhr = t.context.xhr as any;
|
||||
xhr.nodejsSet({baseUrl: 'https://base.url/dir/file.html'});
|
||||
const parsedUrl = xhr._parseUrl('//domain.com/path/to.js');
|
||||
t.truthy(parsedUrl);
|
||||
t.true(parsedUrl.hasOwnProperty('href'));
|
||||
t.is(parsedUrl.href, 'https://domain.com/path/to.js');
|
||||
});
|
@ -0,0 +1,120 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('XMLHttpRequest when redirected issues a GET for the next location', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/redirect/302/method`);
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /GET/i);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
t.fail();
|
||||
resolve();
|
||||
};
|
||||
xhr.send('This should be dropped during the redirect');
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest when redirected does not return the redirect headers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/redirect/302/method`);
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.getResponseHeader('Content-Type'), 'text/plain; charset=utf-8');
|
||||
t.falsy(xhr.getResponseHeader('X-Redirect-Header'));
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
t.fail();
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest when redirected persists custom request headers across redirects', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/redirect/302/headers`);
|
||||
xhr.setRequestHeader('X-Redirect-Test', 'should be preserved');
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/);
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.is(headers.connection, 'keep-alive');
|
||||
t.true(headers.hasOwnProperty('host'));
|
||||
t.is(headers.host, `localhost:${HttpServer.port}`);
|
||||
t.true(headers.hasOwnProperty('x-redirect-test'));
|
||||
t.is(headers['x-redirect-test'], 'should be preserved');
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
t.fail();
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest when redirected drops content-related headers across redirects', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/redirect/302/headers`);
|
||||
xhr.setRequestHeader('X-Redirect-Test', 'should be preserved');
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/);
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.is(headers.connection, 'keep-alive');
|
||||
t.true(headers.hasOwnProperty('host'));
|
||||
t.is(headers.host, `localhost:${HttpServer.port}`);
|
||||
t.true(headers.hasOwnProperty('x-redirect-test'));
|
||||
t.is(headers['x-redirect-test'], 'should be preserved');
|
||||
t.false(headers.hasOwnProperty('content-type'));
|
||||
t.false(headers.hasOwnProperty('content-length'));
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
t.fail();
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest when redirected provides the final responseURL', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/redirect/302/method`);
|
||||
xhr.setRequestHeader('X-Redirect-Test', 'should be preserved');
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.responseUrl, `http://localhost:${HttpServer.port}/_/method`);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
t.fail();
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
@ -0,0 +1,134 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
import { PNGArrayBuffer, PNGBuffer } from './helpers/png';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest(),
|
||||
jsonUrl: '',
|
||||
jsonString: '',
|
||||
imageUrl: ''
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
t.context.jsonUrl = `http://localhost:${HttpServer.port}/test/fixtures/hello.json`;
|
||||
t.context.jsonString = '{"hello": "world", "answer": 42}\n';
|
||||
t.context.imageUrl = `http://localhost:${HttpServer.port}/test/fixtures/hello.png`;
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType text reads a JSON file into a String', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('load', () => {
|
||||
t.is(xhr.response, t.context.jsonString);
|
||||
t.is(xhr.responseText, t.context.jsonString);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.jsonUrl);
|
||||
xhr.responseType = 'text';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType json reads a JSON file into a parsed JSON object', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('readystatechange', () => {
|
||||
if (xhr.readyState !== XMLHttpRequest.DONE) { return; }
|
||||
|
||||
t.deepEqual(xhr.response, { hello: 'world', answer: 42 });
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.jsonUrl);
|
||||
xhr.responseType = 'json';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType json produces null when reading a non-JSON file', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('loadend', () => {
|
||||
t.is(xhr.response, null);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/test/fixtures/hello.txt`);
|
||||
xhr.responseType = 'json';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType arraybuffer reads a JSON file into an ArrayBuffer', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('loadend', () => {
|
||||
t.true(xhr.response instanceof ArrayBuffer);
|
||||
if (!(xhr.response instanceof ArrayBuffer)) { return; }
|
||||
const view = new Uint8Array(xhr.response);
|
||||
const response = Array.from(view).map(viewElement => String.fromCharCode(viewElement)).join('');
|
||||
t.is(response, t.context.jsonString);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.jsonUrl);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType arraybuffer reads a binary file into an ArrayBuffer', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('loadend', () => {
|
||||
t.true(xhr.response instanceof ArrayBuffer);
|
||||
if (!(xhr.response instanceof ArrayBuffer)) { return; }
|
||||
t.deepEqual(xhr.response, PNGArrayBuffer);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.imageUrl);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType buffer reads a JSON file into a node.js Buffer', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('loadend', () => {
|
||||
t.true(xhr.response instanceof Buffer);
|
||||
if (!(xhr.response instanceof Buffer)) { return; }
|
||||
const response = Array.from(xhr.response).map(viewElement => String.fromCharCode(viewElement)).join('');
|
||||
t.is(response, t.context.jsonString);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.jsonUrl);
|
||||
xhr.responseType = 'buffer';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseType buffer reads a binary file into a node.js Buffer', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.addEventListener('loadend', () => {
|
||||
t.true(xhr.response instanceof Buffer);
|
||||
if (!(xhr.response instanceof Buffer)) { return; }
|
||||
t.deepEqual(xhr.response, PNGBuffer);
|
||||
resolve();
|
||||
});
|
||||
xhr.open('GET', t.context.imageUrl);
|
||||
xhr.responseType = 'buffer';
|
||||
xhr.send();
|
||||
});
|
||||
});
|
@ -0,0 +1,46 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseURL provides the URL of the response', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/method`);
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.responseUrl, `http://localhost:${HttpServer.port}/_/method`);
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #responseURL ignores the hash fragment', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/_/method#foo`);
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.responseUrl, `http://localhost:${HttpServer.port}/_/method`);
|
||||
resolve();
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
@ -0,0 +1,137 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
import { PNGArrayBuffer, PNGUint8Array } from './helpers/png';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
t.context.xhr.open('POST', `http://localhost:${HttpServer.port}/_/echo`);
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with ASCII DOMStrings', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(2);
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.getResponseHeader('content-type'), /^text\/plain(;\s?charset=UTF-8)?$/);
|
||||
t.is(xhr.responseText, 'Hello world!');
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send('Hello world!');
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with UTF-8 DOMStrings', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(2);
|
||||
await new Promise(resolve => {
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.getResponseHeader('content-type'), /^text\/plain(;\s?charset=UTF-8)?$/);
|
||||
t.is(xhr.responseText, '世界你好!');
|
||||
resolve();
|
||||
};
|
||||
xhr.send('世界你好!');
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with ArrayBufferViews', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(2);
|
||||
await new Promise(resolve => {
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.getResponseHeader('content-type'), null);
|
||||
if (!(xhr.response instanceof ArrayBuffer)) { t.fail(); return resolve(); }
|
||||
t.deepEqual(new Uint8Array(xhr.response), PNGUint8Array);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send(PNGUint8Array);
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with ArrayBufferViews with set index and length', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(2);
|
||||
const arrayBufferView10 = new Uint8Array(PNGArrayBuffer, 10, 42);
|
||||
await new Promise(resolve => {
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.getResponseHeader('content-type'), null);
|
||||
if (!(xhr.response instanceof ArrayBuffer)) { t.fail(); return resolve(); }
|
||||
t.deepEqual(new Uint8Array(xhr.response), arrayBufferView10);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send(arrayBufferView10);
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with ArrayBuffers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.plan(2);
|
||||
await new Promise(resolve => {
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.getResponseHeader('content-type'), null);
|
||||
if (!(xhr.response instanceof ArrayBuffer)) { t.fail(); return resolve(); }
|
||||
t.deepEqual(xhr.response, PNGArrayBuffer);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send(PNGArrayBuffer);
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send works with node.js Buffers', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
const buffer = Buffer.alloc(PNGUint8Array.length);
|
||||
for (let i = 0; i < PNGUint8Array.length; i++) { buffer.writeUInt8(PNGUint8Array[i], i); }
|
||||
t.plan(2);
|
||||
|
||||
await new Promise(resolve => {
|
||||
xhr.responseType = 'buffer';
|
||||
xhr.onload = () => {
|
||||
t.is(xhr.getResponseHeader('content-type'), null);
|
||||
if (!(xhr.response instanceof Buffer)) { t.fail(); return resolve(); }
|
||||
t.deepEqual(new Uint8Array(xhr.response), PNGUint8Array);
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send(PNGArrayBuffer);
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #send sets POST headers correctly when given null data', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('POST', `http://localhost:${HttpServer.port}/_/headers`);
|
||||
await new Promise(resolve => {
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = () => {
|
||||
t.regex(xhr.responseText, /^\{.*\}$/);
|
||||
const headers = JSON.parse(xhr.responseText);
|
||||
t.true(headers.hasOwnProperty('content-length'));
|
||||
t.is(headers['content-length'], '0');
|
||||
t.false(headers.hasOwnProperty('content-type'));
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = () => { t.fail(); return resolve(); };
|
||||
xhr.send();
|
||||
});
|
||||
});
|
@ -0,0 +1,84 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer } from './helpers/server';
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest(),
|
||||
okUrl: '',
|
||||
errorUrl: '',
|
||||
errorJson: ''
|
||||
}));
|
||||
|
||||
test.before(async () => {
|
||||
await HttpServer.serverStarted;
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
t.context.okUrl = `http://localhost:${HttpServer.port}/test/fixtures/hello.txt`;
|
||||
t.context.errorUrl = `http://localhost:${HttpServer.port}/_/response`;
|
||||
t.context.errorJson = JSON.stringify({
|
||||
code: 401,
|
||||
status: 'Unauthorized',
|
||||
body: JSON.stringify({error: 'Credential error'}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': '28'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #status is 200 for a normal request', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('GET', t.context.okUrl);
|
||||
let done = false;
|
||||
xhr.addEventListener('readystatechange', () => {
|
||||
if (done) { return; }
|
||||
if (xhr.readyState < XMLHttpRequest.HEADERS_RECEIVED) {
|
||||
t.is(xhr.status, 0);
|
||||
t.is(xhr.statusText, '');
|
||||
} else {
|
||||
t.is(xhr.status, 200);
|
||||
t.truthy(xhr.statusText);
|
||||
t.not(xhr.statusText, '');
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
done = true;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('XMLHttpRequest #status returns the server-reported status', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
await new Promise(resolve => {
|
||||
xhr.open('POST', t.context.errorUrl);
|
||||
let done = false;
|
||||
xhr.addEventListener('readystatechange', () => {
|
||||
if (done) { return; }
|
||||
if (xhr.readyState < XMLHttpRequest.HEADERS_RECEIVED) {
|
||||
t.is(xhr.status, 0);
|
||||
t.is(xhr.statusText, '');
|
||||
} else {
|
||||
t.is(xhr.status, 401);
|
||||
t.truthy(xhr.statusText);
|
||||
t.not(xhr.statusText, '');
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
done = true;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
xhr.send(t.context.errorJson);
|
||||
});
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"lib": [ "es5", "es6", "es2016", "es2017", "dom" ]
|
||||
},
|
||||
"include": [
|
||||
"*.spec.ts",
|
||||
"./png.d.ts"
|
||||
]
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
import * as ava from 'ava';
|
||||
import { XMLHttpRequest } from '../xml-http-request';
|
||||
import { HttpServer, HttpsServer } from './helpers/server';
|
||||
import * as https from 'https';
|
||||
|
||||
const agent = new https.Agent({
|
||||
rejectUnauthorized: true,
|
||||
ca: HttpsServer.sslCertificate()
|
||||
});
|
||||
XMLHttpRequest.nodejsSet({
|
||||
httpsAgent: agent
|
||||
});
|
||||
|
||||
function contextualize<T>(getContext: () => T): ava.RegisterContextual<T> {
|
||||
ava.test.beforeEach(t => {
|
||||
Object.assign(t.context, getContext());
|
||||
});
|
||||
return ava.test;
|
||||
}
|
||||
|
||||
const test = contextualize(() => ({
|
||||
xhr: new XMLHttpRequest()
|
||||
}));
|
||||
|
||||
test.before(async t => {
|
||||
await HttpServer.serverStarted;
|
||||
await HttpsServer.serverStarted;
|
||||
|
||||
XMLHttpRequest.nodejsSet({
|
||||
baseUrl: HttpServer.testUrl().replace('https://', 'http://')
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(t => {
|
||||
t.context.xhr = new XMLHttpRequest();
|
||||
});
|
||||
|
||||
test('constructor', t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.is(xhr.readyState, XMLHttpRequest.UNSENT, 'sets readyState to UNSENT');
|
||||
t.is(xhr.timeout, 0, 'sets timeout to 0');
|
||||
t.is(xhr.responseType, '', 'sets responseType to ""');
|
||||
t.is(xhr.status, 0, 'sets status to 0');
|
||||
t.is(xhr.statusText, '', 'sets statusText to ""');
|
||||
});
|
||||
|
||||
test('#open throws SecurityError on CONNECT', t => {
|
||||
t.throws(() => t.context.xhr.open('CONNECT', `http://localhost:${HttpServer.port}/test`), XMLHttpRequest.SecurityError);
|
||||
});
|
||||
|
||||
test('#open with a GET for a local https request', t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('GET', `https://localhost:${HttpsServer.port}/test/fixtures/hello.txt`);
|
||||
t.is(xhr.readyState, XMLHttpRequest.OPENED, 'sets readyState to OPENED');
|
||||
t.is(xhr.status, 0, 'keeps status 0');
|
||||
t.is(xhr.statusText, '', 'keeps statusText ""');
|
||||
});
|
||||
|
||||
test('#send on a local http GET kicks off the request', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('GET', `http://localhost:${HttpServer.port}/test/fixtures/hello.txt`);
|
||||
|
||||
t.plan(2);
|
||||
await new Promise((resolve, reject) => {
|
||||
xhr.onload = (event) => {
|
||||
t.is(xhr.status, 200, 'the status is 200');
|
||||
t.is(xhr.responseText, 'Hello, world!', 'the text is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = (event) => {
|
||||
reject(event);
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('#send on a local https GET kicks off the request', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('GET', `https://localhost:${HttpsServer.port}/test/fixtures/hello.txt`);
|
||||
|
||||
t.plan(2);
|
||||
await new Promise((resolve, reject) => {
|
||||
xhr.onload = (event) => {
|
||||
t.is(xhr.status, 200, 'the status is 200');
|
||||
t.is(xhr.responseText, 'Hello, world!', 'the text is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = (event) => {
|
||||
reject(event);
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('on a local relative GET it kicks off the request', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
xhr.open('GET', '../fixtures/hello.txt');
|
||||
|
||||
t.plan(2);
|
||||
await new Promise((resolve, reject) => {
|
||||
xhr.onload = (event) => {
|
||||
t.is(xhr.status, 200, 'the status is 200');
|
||||
t.is(xhr.responseText, 'Hello, world!', 'the text is correct');
|
||||
resolve();
|
||||
};
|
||||
xhr.onerror = (event) => {
|
||||
reject(event);
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
|
||||
test('on a local gopher GET #open + #send throws a NetworkError', async t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.throws(() => {
|
||||
xhr.open('GET', `gopher:localhost:${HttpServer.port}`);
|
||||
xhr.send();
|
||||
}, XMLHttpRequest.NetworkError);
|
||||
});
|
||||
|
||||
test('readyState constants', t => {
|
||||
t.is(XMLHttpRequest.UNSENT < XMLHttpRequest.OPENED, true, 'UNSENT < OPENED');
|
||||
t.is(XMLHttpRequest.OPENED < XMLHttpRequest.HEADERS_RECEIVED, true, 'OPENED < HEADERS_RECEIVED');
|
||||
t.is(XMLHttpRequest.HEADERS_RECEIVED < XMLHttpRequest.LOADING, true, 'HEADERS_RECEIVED < LOADING');
|
||||
t.is(XMLHttpRequest.LOADING < XMLHttpRequest.DONE, true, 'LOADING < DONE');
|
||||
});
|
||||
|
||||
test('XMLHttpRequest constants match the instance constants', t => {
|
||||
const xhr = t.context.xhr;
|
||||
t.is(XMLHttpRequest.UNSENT, xhr.UNSENT, 'UNSENT');
|
||||
t.is(XMLHttpRequest.OPENED, xhr.OPENED, 'OPENED');
|
||||
t.is(XMLHttpRequest.HEADERS_RECEIVED, xhr.HEADERS_RECEIVED, 'HEADERS_RECEIVED');
|
||||
t.is(XMLHttpRequest.LOADING, xhr.LOADING, 'LOADING');
|
||||
t.is(XMLHttpRequest.DONE, xhr.DONE, 'DONE');
|
||||
});
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "dist",
|
||||
"lib": [ "es5", "es6", "es2016", "es2017", "dom" ]
|
||||
},
|
||||
"files": [
|
||||
"index.ts"
|
||||
]
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
{
|
||||
"rules": {
|
||||
"arrow-return-shorthand": true,
|
||||
"callable-types": true,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space"
|
||||
],
|
||||
"curly": true,
|
||||
"eofline": true,
|
||||
"forin": true,
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs"
|
||||
],
|
||||
"import-spacing": true,
|
||||
"indent": [
|
||||
true,
|
||||
"tabs"
|
||||
],
|
||||
"interface-over-type-literal": true,
|
||||
"label-position": true,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-arg": true,
|
||||
"no-bitwise": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-construct": true,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-super": true,
|
||||
"no-empty": false,
|
||||
"no-empty-interface": true,
|
||||
"no-eval": true,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-misused-new": true,
|
||||
"no-non-null-assertion": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-string-literal": false,
|
||||
"no-string-throw": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unnecessary-initializer": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-open-brace",
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-whitespace"
|
||||
],
|
||||
"prefer-const": true,
|
||||
"quotemark": [
|
||||
true,
|
||||
"single"
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": [
|
||||
true,
|
||||
"always"
|
||||
],
|
||||
"triple-equals": [
|
||||
true,
|
||||
"allow-null-check"
|
||||
],
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
}
|
||||
],
|
||||
"typeof-compare": true,
|
||||
"unified-signatures": true,
|
||||
"variable-name": false,
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
module.exports = function (wallaby) {
|
||||
return {
|
||||
files: ['**/*.ts', '*.ts', '!test/**/*'],
|
||||
tests: ['test/**/*.ts'],
|
||||
env: {type: 'node'},
|
||||
testFramework: 'ava',
|
||||
recycle: true,
|
||||
name: 'XMLHttpRequest 2+',
|
||||
slowTestThreshold: 300,
|
||||
reportUnhandledPromises: false,
|
||||
workers: {
|
||||
// initial: 1,
|
||||
// regular: 1,
|
||||
recycle: true
|
||||
},
|
||||
compilers: {
|
||||
'**/*.ts': wallaby.compilers.typeScript({
|
||||
target: 'es2015',
|
||||
module: 'commonjs',
|
||||
sourceMap: true,
|
||||
experimentalDecorators: true,
|
||||
emitDecoratorMetadata: true,
|
||||
lib: ['es5', 'es6', 'es2016', 'es2017', 'dom']
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,49 @@
|
||||
import { ProgressEvent } from './progress-event';
|
||||
|
||||
export type ProgressEventListener = (event: ProgressEvent) => void;
|
||||
export type ProgressEventListenerObject = {handleEvent(event: ProgressEvent): void};
|
||||
export type ProgressEventListenerOrEventListenerObject = ProgressEventListener | ProgressEventListenerObject;
|
||||
|
||||
export class XMLHttpRequestEventTarget {
|
||||
onloadstart: ProgressEventListener | null;
|
||||
onprogress: ProgressEventListener | null;
|
||||
onabort: ProgressEventListener | null;
|
||||
onerror: ProgressEventListener | null;
|
||||
onload: ProgressEventListener | null;
|
||||
ontimeout: ProgressEventListener | null;
|
||||
onloadend: ProgressEventListener | null;
|
||||
|
||||
private listeners: {[eventType: string]: ProgressEventListener[]} = {};
|
||||
|
||||
addEventListener(eventType: string, listener?: ProgressEventListenerOrEventListenerObject) {
|
||||
eventType = eventType.toLowerCase();
|
||||
this.listeners[eventType] = this.listeners[eventType] || [];
|
||||
this.listeners[eventType].push((listener as ProgressEventListenerObject).handleEvent || (listener as ProgressEventListener));
|
||||
}
|
||||
removeEventListener(eventType: string, listener?: ProgressEventListenerOrEventListenerObject) {
|
||||
eventType = eventType.toLowerCase();
|
||||
if (!this.listeners[eventType]) { return; }
|
||||
|
||||
const index = this.listeners[eventType].indexOf((listener as ProgressEventListenerObject).handleEvent || (listener as ProgressEventListener));
|
||||
if (index < 0) { return; }
|
||||
|
||||
this.listeners[eventType].splice(index, 1);
|
||||
}
|
||||
dispatchEvent(event: ProgressEvent) {
|
||||
const eventType = event.type.toLowerCase();
|
||||
event.target = this; // TODO: set event.currentTarget?
|
||||
|
||||
if (this.listeners[eventType]) {
|
||||
for (let listener of this.listeners[eventType]) {
|
||||
listener.call(this, event);
|
||||
}
|
||||
}
|
||||
|
||||
const listener = this[`on${eventType}`];
|
||||
if (listener) {
|
||||
listener.call(this, event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
import { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
import { ClientRequest } from 'http';
|
||||
|
||||
export class XMLHttpRequestUpload extends XMLHttpRequestEventTarget {
|
||||
private _contentType: string | null = null;
|
||||
private _body = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._reset();
|
||||
}
|
||||
|
||||
_reset() {
|
||||
this._contentType = null;
|
||||
this._body = null;
|
||||
}
|
||||
|
||||
_setData(data?: string | Buffer | ArrayBuffer | ArrayBufferView) {
|
||||
if (data == null) { return; }
|
||||
|
||||
if (typeof data === 'string') {
|
||||
if (data.length !== 0) {
|
||||
this._contentType = 'text/plain;charset=UTF-8';
|
||||
}
|
||||
this._body = Buffer.from(data, 'utf-8');
|
||||
} else if (Buffer.isBuffer(data)) {
|
||||
this._body = data;
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
const body = Buffer.alloc(data.byteLength);
|
||||
const view = new Uint8Array(data);
|
||||
for (let i = 0; i < data.byteLength; i++) { body[i] = view[i]; }
|
||||
this._body = body;
|
||||
} else if (data.buffer && data.buffer instanceof ArrayBuffer) {
|
||||
const body = Buffer.alloc(data.byteLength);
|
||||
const offset = data.byteOffset;
|
||||
const view = new Uint8Array(data.buffer);
|
||||
for (let i = 0; i < data.byteLength; i++) { body[i] = view[i + offset]; }
|
||||
this._body = body;
|
||||
} else {
|
||||
throw new Error(`Unsupported send() data ${data}`);
|
||||
}
|
||||
}
|
||||
|
||||
_finalizeHeaders(headers: object, loweredHeaders: object) {
|
||||
if (this._contentType && !loweredHeaders['content-type']) {
|
||||
headers['Content-Type'] = this._contentType;
|
||||
}
|
||||
if (this._body) {
|
||||
headers['Content-Length'] = this._body.length.toString();
|
||||
}
|
||||
}
|
||||
|
||||
_startUpload(request: ClientRequest) {
|
||||
if (this._body) { request.write(this._body); }
|
||||
request.end();
|
||||
}
|
||||
}
|
@ -0,0 +1,471 @@
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import * as os from 'os';
|
||||
import * as url from 'url';
|
||||
import { ProgressEvent } from './progress-event';
|
||||
import { InvalidStateError, NetworkError, SecurityError, SyntaxError } from './errors';
|
||||
import { ProgressEventListener, XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
||||
import { XMLHttpRequestUpload } from './xml-http-request-upload';
|
||||
import { Url } from 'url';
|
||||
import { Agent as HttpAgent, ClientRequest, IncomingMessage, RequestOptions as RequestOptionsHttp } from 'http';
|
||||
import { Agent as HttpsAgent } from 'https';
|
||||
import * as Cookie from 'cookiejar';
|
||||
|
||||
export interface XMLHttpRequestOptions {
|
||||
anon?: boolean;
|
||||
}
|
||||
export interface XHRUrl extends Url {
|
||||
method?: string;
|
||||
}
|
||||
|
||||
export class XMLHttpRequest extends XMLHttpRequestEventTarget {
|
||||
static ProgressEvent = ProgressEvent;
|
||||
static InvalidStateError = InvalidStateError;
|
||||
static NetworkError = NetworkError;
|
||||
static SecurityError = SecurityError;
|
||||
static SyntaxError = SyntaxError;
|
||||
static XMLHttpRequestUpload = XMLHttpRequestUpload;
|
||||
|
||||
static UNSENT = 0;
|
||||
static OPENED = 1;
|
||||
static HEADERS_RECEIVED = 2;
|
||||
static LOADING = 3;
|
||||
static DONE = 4;
|
||||
|
||||
static cookieJar = Cookie.CookieJar();
|
||||
|
||||
UNSENT = XMLHttpRequest.UNSENT;
|
||||
OPENED = XMLHttpRequest.OPENED;
|
||||
HEADERS_RECEIVED = XMLHttpRequest.HEADERS_RECEIVED;
|
||||
LOADING = XMLHttpRequest.LOADING;
|
||||
DONE = XMLHttpRequest.DONE;
|
||||
|
||||
onreadystatechange: ProgressEventListener | null = null;
|
||||
readyState: number = XMLHttpRequest.UNSENT;
|
||||
|
||||
response: string | ArrayBuffer | Buffer | object | null = null;
|
||||
responseText = '';
|
||||
responseType = '';
|
||||
status = 0; // TODO: UNSENT?
|
||||
statusText = '';
|
||||
timeout = 0;
|
||||
upload = new XMLHttpRequestUpload();
|
||||
responseUrl = '';
|
||||
withCredentials = false;
|
||||
|
||||
nodejsHttpAgent: HttpsAgent;
|
||||
nodejsHttpsAgent: HttpsAgent;
|
||||
nodejsBaseUrl: string | null;
|
||||
|
||||
private _anonymous: boolean;
|
||||
private _method: string | null = null;
|
||||
private _url: XHRUrl | null = null;
|
||||
private _sync = false;
|
||||
private _headers: {[header: string]: string} = {};
|
||||
private _loweredHeaders: {[lowercaseHeader: string]: string} = {};
|
||||
private _mimeOverride: string | null = null; // TODO: is type right?
|
||||
private _request: ClientRequest | null = null;
|
||||
private _response: IncomingMessage | null = null;
|
||||
private _responseParts: Buffer[] | null = null;
|
||||
private _responseHeaders: {[lowercaseHeader: string]: string} | null = null;
|
||||
private _aborting = null; // TODO: type?
|
||||
private _error = null; // TODO: type?
|
||||
private _loadedBytes = 0;
|
||||
private _totalBytes = 0;
|
||||
private _lengthComputable = false;
|
||||
|
||||
private _restrictedMethods = {CONNECT: true, TRACE: true, TRACK: true};
|
||||
private _restrictedHeaders = {
|
||||
'accept-charset': true,
|
||||
'accept-encoding': true,
|
||||
'access-control-request-headers': true,
|
||||
'access-control-request-method': true,
|
||||
connection: true,
|
||||
'content-length': true,
|
||||
cookie: true,
|
||||
cookie2: true,
|
||||
date: true,
|
||||
dnt: true,
|
||||
expect: true,
|
||||
host: true,
|
||||
'keep-alive': true,
|
||||
origin: true,
|
||||
referer: true,
|
||||
te: true,
|
||||
trailer: true,
|
||||
'transfer-encoding': true,
|
||||
upgrade: true,
|
||||
'user-agent': true,
|
||||
via: true
|
||||
};
|
||||
private _privateHeaders = {'set-cookie': true, 'set-cookie2': true};
|
||||
|
||||
//Redacted private information (${os.type()} ${os.arch()}) node.js/${process.versions.node} v8/${process.versions.v8} from the original version @ github
|
||||
//Pretend to be tor-browser https://blog.torproject.org/browser-fingerprinting-introduction-and-challenges-ahead/
|
||||
private _userAgent = `Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0`;
|
||||
|
||||
constructor(options: XMLHttpRequestOptions = {}) {
|
||||
super();
|
||||
this._anonymous = options.anon || false;
|
||||
}
|
||||
|
||||
open(method: string, url: string, async = true, user?: string, password?: string) {
|
||||
method = method.toUpperCase();
|
||||
if (this._restrictedMethods[method]) { throw new XMLHttpRequest.SecurityError(`HTTP method ${method} is not allowed in XHR`)};
|
||||
|
||||
const xhrUrl = this._parseUrl(url, user, password);
|
||||
|
||||
if (this.readyState === XMLHttpRequest.HEADERS_RECEIVED || this.readyState === XMLHttpRequest.LOADING) {
|
||||
// TODO(pwnall): terminate abort(), terminate send()
|
||||
}
|
||||
|
||||
this._method = method;
|
||||
this._url = xhrUrl;
|
||||
this._sync = !async;
|
||||
this._headers = {};
|
||||
this._loweredHeaders = {};
|
||||
this._mimeOverride = null;
|
||||
this._setReadyState(XMLHttpRequest.OPENED);
|
||||
this._request = null;
|
||||
this._response = null;
|
||||
this.status = 0;
|
||||
this.statusText = '';
|
||||
this._responseParts = [];
|
||||
this._responseHeaders = null;
|
||||
this._loadedBytes = 0;
|
||||
this._totalBytes = 0;
|
||||
this._lengthComputable = false;
|
||||
}
|
||||
|
||||
setRequestHeader(name: string, value: any) {
|
||||
if (this.readyState !== XMLHttpRequest.OPENED) { throw new XMLHttpRequest.InvalidStateError('XHR readyState must be OPENED'); }
|
||||
|
||||
const loweredName = name.toLowerCase();
|
||||
if (this._restrictedHeaders[loweredName] || /^sec-/.test(loweredName) || /^proxy-/.test(loweredName)) {
|
||||
console.warn(`Refused to set unsafe header "${name}"`);
|
||||
return;
|
||||
}
|
||||
|
||||
value = value.toString();
|
||||
if (this._loweredHeaders[loweredName] != null) {
|
||||
name = this._loweredHeaders[loweredName];
|
||||
this._headers[name] = `${this._headers[name]}, ${value}`;
|
||||
} else {
|
||||
this._loweredHeaders[loweredName] = name;
|
||||
this._headers[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
send(data?: string | Buffer | ArrayBuffer | ArrayBufferView) {
|
||||
if (this.readyState !== XMLHttpRequest.OPENED) { throw new XMLHttpRequest.InvalidStateError('XHR readyState must be OPENED'); }
|
||||
if (this._request) { throw new XMLHttpRequest.InvalidStateError('send() already called'); }
|
||||
|
||||
switch (this._url.protocol) {
|
||||
case 'file:':
|
||||
return this._sendFile(data);
|
||||
case 'http:':
|
||||
case 'https:':
|
||||
return this._sendHttp(data);
|
||||
default:
|
||||
throw new XMLHttpRequest.NetworkError(`Unsupported protocol ${this._url.protocol}`);
|
||||
}
|
||||
}
|
||||
|
||||
abort() {
|
||||
if (this._request == null) { return; }
|
||||
|
||||
this._request.abort();
|
||||
this._setError();
|
||||
|
||||
this._dispatchProgress('abort');
|
||||
this._dispatchProgress('loadend');
|
||||
}
|
||||
|
||||
getResponseHeader(name: string) {
|
||||
if (this._responseHeaders == null || name == null) { return null; }
|
||||
const loweredName = name.toLowerCase();
|
||||
return this._responseHeaders.hasOwnProperty(loweredName)
|
||||
? this._responseHeaders[name.toLowerCase()]
|
||||
: null;
|
||||
}
|
||||
|
||||
getAllResponseHeaders() {
|
||||
if (this._responseHeaders == null) { return ''; }
|
||||
return Object.keys(this._responseHeaders).map(key => `${key}: ${this._responseHeaders[key]}`).join('\r\n');
|
||||
}
|
||||
|
||||
overrideMimeType(mimeType: string) {
|
||||
if (this.readyState === XMLHttpRequest.LOADING || this.readyState === XMLHttpRequest.DONE) { throw new XMLHttpRequest.InvalidStateError('overrideMimeType() not allowed in LOADING or DONE'); }
|
||||
this._mimeOverride = mimeType.toLowerCase();
|
||||
}
|
||||
|
||||
nodejsSet(options: {httpAgent?: HttpAgent, httpsAgent?: HttpsAgent, baseUrl?: string }) {
|
||||
this.nodejsHttpAgent = options.httpAgent || this.nodejsHttpAgent;
|
||||
this.nodejsHttpsAgent = options.httpsAgent || this.nodejsHttpsAgent;
|
||||
if (options.hasOwnProperty('baseUrl')) {
|
||||
if (options.baseUrl != null) {
|
||||
const parsedUrl = url.parse(options.baseUrl, false, true);
|
||||
if (!parsedUrl.protocol) {
|
||||
throw new XMLHttpRequest.SyntaxError("baseUrl must be an absolute URL")
|
||||
}
|
||||
}
|
||||
this.nodejsBaseUrl = options.baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
static nodejsSet(options: {httpAgent?: HttpAgent, httpsAgent?: HttpsAgent, baseUrl?: string }) {
|
||||
XMLHttpRequest.prototype.nodejsSet(options);
|
||||
}
|
||||
|
||||
private _setReadyState(readyState: number) {
|
||||
this.readyState = readyState;
|
||||
this.dispatchEvent(new ProgressEvent('readystatechange'));
|
||||
}
|
||||
|
||||
private _sendFile(data: any) {
|
||||
// TODO
|
||||
throw new Error('Protocol file: not implemented');
|
||||
}
|
||||
|
||||
private _sendHttp(data?: string | Buffer | ArrayBuffer | ArrayBufferView) {
|
||||
if (this._sync) { throw new Error('Synchronous XHR processing not implemented'); }
|
||||
if (data && (this._method === 'GET' || this._method === 'HEAD')) {
|
||||
console.warn(`Discarding entity body for ${this._method} requests`);
|
||||
data = null;
|
||||
} else {
|
||||
data = data || '';
|
||||
}
|
||||
|
||||
this.upload._setData(data);
|
||||
this._finalizeHeaders();
|
||||
this._sendHxxpRequest();
|
||||
}
|
||||
|
||||
private _sendHxxpRequest() {
|
||||
if (this.withCredentials) {
|
||||
const cookie = XMLHttpRequest.cookieJar
|
||||
.getCookies(
|
||||
Cookie.CookieAccessInfo(this._url.hostname, this._url.pathname, this._url.protocol === 'https:')
|
||||
).toValueString();
|
||||
|
||||
this._headers.cookie = this._headers.cookie2 = cookie;
|
||||
}
|
||||
|
||||
const [hxxp, agent] = this._url.protocol === 'http:' ? [http, this.nodejsHttpAgent] : [https, this.nodejsHttpsAgent];
|
||||
const requestMethod: (options: RequestOptionsHttp) => ClientRequest = hxxp.request.bind(hxxp);
|
||||
const request = requestMethod({
|
||||
hostname: this._url.hostname,
|
||||
port: +this._url.port,
|
||||
path: this._url.path,
|
||||
auth: this._url.auth,
|
||||
method: this._method,
|
||||
headers: this._headers,
|
||||
agent
|
||||
});
|
||||
this._request = request;
|
||||
|
||||
if (this.timeout) { request.setTimeout(this.timeout, () => this._onHttpTimeout(request)); }
|
||||
request.on('response', response => this._onHttpResponse(request, response));
|
||||
request.on('error', error => this._onHttpRequestError(request, error));
|
||||
this.upload._startUpload(request);
|
||||
|
||||
if (this._request === request) { this._dispatchProgress('loadstart'); }
|
||||
}
|
||||
|
||||
private _finalizeHeaders() {
|
||||
this._headers = {
|
||||
...this._headers,
|
||||
Connection: 'keep-alive',
|
||||
Host: this._url.host,
|
||||
'User-Agent': this._userAgent,
|
||||
...this._anonymous ? {Referer: 'about:blank'} : {}
|
||||
};
|
||||
this.upload._finalizeHeaders(this._headers, this._loweredHeaders);
|
||||
}
|
||||
|
||||
private _onHttpResponse(request: ClientRequest, response: IncomingMessage) {
|
||||
if (this._request !== request) { return; }
|
||||
|
||||
if (this.withCredentials && (response.headers['set-cookie'] || response.headers['set-cookie2'])) {
|
||||
XMLHttpRequest.cookieJar
|
||||
.setCookies(response.headers['set-cookie'] || response.headers['set-cookie2']);
|
||||
}
|
||||
|
||||
if ([301, 302, 303, 307, 308].indexOf(response.statusCode) >= 0) {
|
||||
this._url = this._parseUrl(response.headers.location);
|
||||
this._method = 'GET';
|
||||
if (this._loweredHeaders['content-type']) {
|
||||
delete this._headers[this._loweredHeaders['content-type']];
|
||||
delete this._loweredHeaders['content-type'];
|
||||
}
|
||||
if (this._headers['Content-Type'] != null) {
|
||||
delete this._headers['Content-Type'];
|
||||
}
|
||||
delete this._headers['Content-Length'];
|
||||
|
||||
this.upload._reset();
|
||||
this._finalizeHeaders();
|
||||
this._sendHxxpRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
this._response = response;
|
||||
this._response.on('data', data => this._onHttpResponseData(response, data));
|
||||
this._response.on('end', () => this._onHttpResponseEnd(response));
|
||||
this._response.on('close', () => this._onHttpResponseClose(response));
|
||||
|
||||
this.responseUrl = this._url.href.split('#')[0];
|
||||
this.status = response.statusCode;
|
||||
this.statusText = http.STATUS_CODES[this.status];
|
||||
this._parseResponseHeaders(response);
|
||||
|
||||
const lengthString = this._responseHeaders['content-length'] || '';
|
||||
this._totalBytes = +lengthString;
|
||||
this._lengthComputable = !!lengthString;
|
||||
|
||||
this._setReadyState(XMLHttpRequest.HEADERS_RECEIVED);
|
||||
}
|
||||
|
||||
private _onHttpResponseData(response: IncomingMessage, data: string | Buffer) {
|
||||
if (this._response !== response) { return; }
|
||||
|
||||
this._responseParts.push(Buffer.from(data as any));
|
||||
this._loadedBytes += data.length;
|
||||
|
||||
if (this.readyState !== XMLHttpRequest.LOADING) {
|
||||
this._setReadyState(XMLHttpRequest.LOADING);
|
||||
}
|
||||
|
||||
this._dispatchProgress('progress');
|
||||
}
|
||||
|
||||
private _onHttpResponseEnd(response: IncomingMessage) {
|
||||
if (this._response !== response) { return; }
|
||||
|
||||
this._parseResponse();
|
||||
this._request = null;
|
||||
this._response = null;
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
|
||||
this._dispatchProgress('load');
|
||||
this._dispatchProgress('loadend');
|
||||
}
|
||||
|
||||
private _onHttpResponseClose(response: IncomingMessage) {
|
||||
if (this._response !== response) { return; }
|
||||
|
||||
const request = this._request;
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
|
||||
this._dispatchProgress('error');
|
||||
this._dispatchProgress('loadend');
|
||||
}
|
||||
|
||||
private _onHttpTimeout(request: ClientRequest) {
|
||||
if (this._request !== request) { return; }
|
||||
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
|
||||
this._dispatchProgress('timeout');
|
||||
this._dispatchProgress('loadend');
|
||||
}
|
||||
|
||||
private _onHttpRequestError(request: ClientRequest, error: Error) {
|
||||
if (this._request !== request) { return; }
|
||||
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
|
||||
this._dispatchProgress('error');
|
||||
this._dispatchProgress('loadend');
|
||||
}
|
||||
|
||||
private _dispatchProgress(eventType: string) {
|
||||
const event = new XMLHttpRequest.ProgressEvent(eventType);
|
||||
event.lengthComputable = this._lengthComputable;
|
||||
event.loaded = this._loadedBytes;
|
||||
event.total = this._totalBytes;
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
private _setError() {
|
||||
this._request = null;
|
||||
this._response = null;
|
||||
this._responseHeaders = null;
|
||||
this._responseParts = null;
|
||||
}
|
||||
|
||||
private _parseUrl(urlString: string, user?: string, password?: string) {
|
||||
const absoluteUrl = this.nodejsBaseUrl == null ? urlString : url.resolve(this.nodejsBaseUrl, urlString);
|
||||
const xhrUrl: XHRUrl = url.parse(absoluteUrl, false, true);
|
||||
|
||||
xhrUrl.hash = null;
|
||||
|
||||
const [xhrUser, xhrPassword] = (xhrUrl.auth || '').split(':');
|
||||
if (xhrUser || xhrPassword || user || password) {
|
||||
xhrUrl.auth = `${user || xhrUser || ''}:${password || xhrPassword || ''}`;
|
||||
}
|
||||
|
||||
return xhrUrl;
|
||||
}
|
||||
|
||||
private _parseResponseHeaders(response: IncomingMessage) {
|
||||
this._responseHeaders = {};
|
||||
for (let name in response.headers) {
|
||||
const loweredName = name.toLowerCase();
|
||||
if (this._privateHeaders[loweredName]) { continue; }
|
||||
this._responseHeaders[loweredName] = response.headers[name];
|
||||
}
|
||||
if (this._mimeOverride != null) {
|
||||
this._responseHeaders['content-type'] = this._mimeOverride;
|
||||
}
|
||||
}
|
||||
|
||||
private _parseResponse() {
|
||||
const buffer = Buffer.concat(this._responseParts);
|
||||
this._responseParts = null;
|
||||
|
||||
switch (this.responseType) {
|
||||
case 'json':
|
||||
this.responseText = null;
|
||||
try {
|
||||
this.response = JSON.parse(buffer.toString('utf-8'));
|
||||
} catch {
|
||||
this.response = null;
|
||||
}
|
||||
return;
|
||||
case 'buffer':
|
||||
this.responseText = null;
|
||||
this.response = buffer;
|
||||
return;
|
||||
case 'arraybuffer':
|
||||
this.responseText = null;
|
||||
const arrayBuffer = new ArrayBuffer(buffer.length);
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < buffer.length; i++) { view[i] = buffer[i]; }
|
||||
this.response = arrayBuffer;
|
||||
return;
|
||||
case 'text':
|
||||
default:
|
||||
try {
|
||||
this.responseText = buffer.toString(this._parseResponseEncoding());
|
||||
} catch {
|
||||
this.responseText = buffer.toString('binary');
|
||||
}
|
||||
this.response = this.responseText;
|
||||
}
|
||||
}
|
||||
|
||||
private _parseResponseEncoding() {
|
||||
return /;\s*charset=(.*)$/.exec(this._responseHeaders['content-type'] || '')[1] || 'utf-8';
|
||||
}
|
||||
}
|
||||
|
||||
XMLHttpRequest.prototype.nodejsHttpAgent = http.globalAgent;
|
||||
XMLHttpRequest.prototype.nodejsHttpsAgent = https.globalAgent;
|
||||
XMLHttpRequest.prototype.nodejsBaseUrl = null;
|
File diff suppressed because it is too large
Load Diff
2171
local_modules/web3-providers-http/package-lock.json
generated
Normal file
2171
local_modules/web3-providers-http/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
local_modules/web3-providers-http/package.json
Normal file
24
local_modules/web3-providers-http/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "web3-providers-http",
|
||||
"version": "1.6.1",
|
||||
"description": "Module to handle web3 RPC connections over HTTP.",
|
||||
"repository": "https://github.com/ethereum/web3.js/tree/1.x/packages/web3-providers-http",
|
||||
"license": "LGPL-3.0",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "tsc -b tsconfig.json",
|
||||
"dtslint": "dtslint --localTs ../../node_modules/typescript/lib types"
|
||||
},
|
||||
"types": "types/index.d.ts",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"web3-core-helpers": "1.6.1",
|
||||
"xhr2-cookies": "file:./local_modules/xhr2-cookies"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dtslint": "^3.4.1",
|
||||
"typescript": "^3.9.5"
|
||||
}
|
||||
}
|
142
local_modules/web3-providers-http/src/index.js
Normal file
142
local_modules/web3-providers-http/src/index.js
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @file httpprovider.js
|
||||
* @authors:
|
||||
* Marek Kotewicz <marek@parity.io>
|
||||
* Marian Oancea
|
||||
* Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2015
|
||||
*/
|
||||
|
||||
var errors = require('web3-core-helpers').errors;
|
||||
var XHR2 = require('xhr2-cookies').XMLHttpRequest; // jshint ignore: line
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
|
||||
|
||||
/**
|
||||
* HttpProvider should be used to send rpc calls over http
|
||||
*/
|
||||
var HttpProvider = function HttpProvider(host, options) {
|
||||
options = options || {};
|
||||
|
||||
this.withCredentials = options.withCredentials || false;
|
||||
this.timeout = options.timeout || 0;
|
||||
this.headers = options.headers;
|
||||
this.agent = options.agent;
|
||||
this.connected = false;
|
||||
|
||||
// keepAlive is true unless explicitly set to false
|
||||
const keepAlive = options.keepAlive !== false;
|
||||
this.host = host || 'http://localhost:8545';
|
||||
if (!this.agent) {
|
||||
if (this.host.substring(0,5) === "https") {
|
||||
this.httpsAgent = new https.Agent({ keepAlive });
|
||||
} else {
|
||||
this.httpAgent = new http.Agent({ keepAlive });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
HttpProvider.prototype._prepareRequest = function(){
|
||||
var request;
|
||||
|
||||
// the current runtime is a browser
|
||||
if (typeof XMLHttpRequest !== 'undefined') {
|
||||
request = new XMLHttpRequest();
|
||||
} else {
|
||||
request = new XHR2();
|
||||
var agents = {httpsAgent: this.httpsAgent, httpAgent: this.httpAgent, baseUrl: this.baseUrl};
|
||||
|
||||
if (this.agent) {
|
||||
agents.httpsAgent = this.agent.https;
|
||||
agents.httpAgent = this.agent.http;
|
||||
agents.baseUrl = this.agent.baseUrl;
|
||||
}
|
||||
|
||||
request.nodejsSet(agents);
|
||||
}
|
||||
|
||||
request.open('POST', this.host, true);
|
||||
request.setRequestHeader('Content-Type','application/json');
|
||||
request.timeout = this.timeout;
|
||||
request.withCredentials = this.withCredentials;
|
||||
|
||||
if(this.headers) {
|
||||
this.headers.forEach(function(header) {
|
||||
request.setRequestHeader(header.name, header.value);
|
||||
});
|
||||
}
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be used to make async request
|
||||
*
|
||||
* @method send
|
||||
* @param {Object} payload
|
||||
* @param {Function} callback triggered on end with (err, result)
|
||||
*/
|
||||
HttpProvider.prototype.send = function (payload, callback) {
|
||||
var _this = this;
|
||||
var request = this._prepareRequest();
|
||||
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState === 4 && request.timeout !== 1) {
|
||||
var result = request.responseText;
|
||||
var error = null;
|
||||
|
||||
try {
|
||||
result = JSON.parse(result);
|
||||
} catch(e) {
|
||||
error = errors.InvalidResponse(request.responseText);
|
||||
}
|
||||
|
||||
_this.connected = true;
|
||||
callback(error, result);
|
||||
}
|
||||
};
|
||||
|
||||
request.ontimeout = function() {
|
||||
_this.connected = false;
|
||||
callback(errors.ConnectionTimeout(this.timeout));
|
||||
};
|
||||
|
||||
try {
|
||||
request.send(JSON.stringify(payload));
|
||||
} catch(error) {
|
||||
this.connected = false;
|
||||
callback(errors.InvalidConnection(this.host));
|
||||
}
|
||||
};
|
||||
|
||||
HttpProvider.prototype.disconnect = function () {
|
||||
//NO OP
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the desired boolean.
|
||||
*
|
||||
* @method supportsSubscriptions
|
||||
* @returns {boolean}
|
||||
*/
|
||||
HttpProvider.prototype.supportsSubscriptions = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
module.exports = HttpProvider;
|
9
local_modules/web3-providers-http/tsconfig.json
Normal file
9
local_modules/web3-providers-http/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
]
|
||||
}
|
66
local_modules/web3-providers-http/types/index.d.ts
vendored
Normal file
66
local_modules/web3-providers-http/types/index.d.ts
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file index.d.ts
|
||||
* @author Josh Stevens <joshstevens19@hotmail.co.uk>
|
||||
* @date 2018
|
||||
*/
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
|
||||
import { HttpProviderBase, JsonRpcResponse } from 'web3-core-helpers';
|
||||
|
||||
export interface HttpHeader {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface HttpProviderAgent {
|
||||
baseUrl?: string;
|
||||
http?: http.Agent;
|
||||
https?: https.Agent;
|
||||
}
|
||||
|
||||
export interface HttpProviderOptions {
|
||||
withCredentials?: boolean;
|
||||
timeout?: number;
|
||||
headers?: HttpHeader[];
|
||||
agent?: HttpProviderAgent;
|
||||
keepAlive?: boolean;
|
||||
}
|
||||
|
||||
export class HttpProvider extends HttpProviderBase {
|
||||
host: string;
|
||||
|
||||
withCredentials: boolean;
|
||||
timeout: number;
|
||||
headers?: HttpHeader[];
|
||||
agent?: HttpProviderAgent;
|
||||
connected: boolean;
|
||||
|
||||
constructor(host?: string, options?: HttpProviderOptions);
|
||||
|
||||
send(
|
||||
payload: object,
|
||||
callback?: (
|
||||
error: Error | null,
|
||||
result: JsonRpcResponse | undefined
|
||||
) => void
|
||||
): void;
|
||||
disconnect(): boolean;
|
||||
supportsSubscriptions(): boolean;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file web3-provider-http-tests.ts
|
||||
* @author Josh Stevens <joshstevens19@hotmail.co.uk> , Samuel Furter <samuel@ethereum.org>
|
||||
* @date 2018
|
||||
*/
|
||||
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import { HttpProvider } from 'web3-providers';
|
||||
import { JsonRpcResponse } from 'web3-core-helpers';
|
||||
|
||||
const httpProvider = new HttpProvider('http://localhost:8545', {
|
||||
timeout: 20000,
|
||||
headers: [
|
||||
{
|
||||
name: 'Access-Control-Allow-Origin',
|
||||
value: '*'
|
||||
}
|
||||
],
|
||||
withCredentials: false,
|
||||
agent: {
|
||||
baseUrl: 'base',
|
||||
http: new http.Agent({}),
|
||||
https: new https.Agent({})
|
||||
}
|
||||
});
|
||||
|
||||
// $ExpectType void
|
||||
httpProvider.send({}, (error: Error | null) => {});
|
||||
|
||||
// $ExpectType void
|
||||
httpProvider.send({}, (error: Error | null, result: JsonRpcResponse | undefined) => {});
|
||||
|
||||
// $ExpectType boolean
|
||||
httpProvider.disconnect();
|
17
local_modules/web3-providers-http/types/tsconfig.json
Normal file
17
local_modules/web3-providers-http/types/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"target": "es6",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"noEmit": true,
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"web3-providers": ["."]
|
||||
}
|
||||
}
|
||||
}
|
10
local_modules/web3-providers-http/types/tslint.json
Normal file
10
local_modules/web3-providers-http/types/tslint.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "dtslint/dtslint.json",
|
||||
"rules": {
|
||||
"semicolon": false,
|
||||
"no-import-default-of-export-equals": false,
|
||||
"file-name-casing": [true, "kebab-case"],
|
||||
"whitespace": false,
|
||||
"no-unnecessary-class": false
|
||||
}
|
||||
}
|
2267
package-lock.json
generated
2267
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,11 @@
|
||||
"circomlib": "git+https://github.com/tornadocash/circomlib.git#3b492f9801573eebcfe1b6c584afe8a3beecf2b4",
|
||||
"commander": "^5.1.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"gas-price-oracle": "^0.2.2",
|
||||
"gas-price-oracle": "^0.4.4",
|
||||
"socks-proxy-agent": "^6.1.1",
|
||||
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
|
||||
"web3": "^1.2.8",
|
||||
"web3": "^1.6.1",
|
||||
"web3-providers-http": "file:./local_modules/web3-providers-http",
|
||||
"websnark": "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
368
yarn.lock
368
yarn.lock
@ -39,6 +39,22 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.0":
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348"
|
||||
integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==
|
||||
dependencies:
|
||||
crc-32 "^1.2.0"
|
||||
ethereumjs-util "^7.1.3"
|
||||
|
||||
"@ethereumjs/tx@^3.3.2":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7"
|
||||
integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==
|
||||
dependencies:
|
||||
"@ethereumjs/common" "^2.6.0"
|
||||
ethereumjs-util "^7.1.3"
|
||||
|
||||
"@ethersproject/abi@5.0.7":
|
||||
version "5.0.7"
|
||||
resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b"
|
||||
@ -232,6 +248,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/bn.js@^5.1.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
|
||||
integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "14.14.14"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
||||
@ -279,6 +302,13 @@ acorn@^7.4.0:
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
agent-base@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.9.1:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
@ -421,6 +451,13 @@ axios@^0.19.2:
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
|
||||
axios@^0.21.2:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
@ -511,6 +548,11 @@ bn.js@^5.0.0, bn.js@^5.1.1:
|
||||
resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
|
||||
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
|
||||
|
||||
bn.js@^5.1.2, bn.js@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
|
||||
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
|
||||
|
||||
body-parser@1.19.0, body-parser@^1.16.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
@ -886,6 +928,14 @@ cors@^2.8.1:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
crc-32@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
|
||||
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
|
||||
dependencies:
|
||||
exit-on-epipe "~1.0.1"
|
||||
printj "~1.1.0"
|
||||
|
||||
create-ecdh@^4.0.0:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
|
||||
@ -976,6 +1026,13 @@ debug@2.6.9, debug@^2.2.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.3.1:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@=3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
@ -1468,6 +1525,17 @@ ethereumjs-util@^6.0.0:
|
||||
ethjs-util "0.1.6"
|
||||
rlp "^2.2.3"
|
||||
|
||||
ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.3:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23"
|
||||
integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==
|
||||
dependencies:
|
||||
"@types/bn.js" "^5.1.0"
|
||||
bn.js "^5.1.2"
|
||||
create-hash "^1.1.2"
|
||||
ethereum-cryptography "^0.1.3"
|
||||
rlp "^2.2.4"
|
||||
|
||||
ethjs-unit@0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"
|
||||
@ -1510,6 +1578,11 @@ execa@^1.0.0:
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
exit-on-epipe@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
||||
|
||||
express@^4.14.0:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
@ -1672,6 +1745,11 @@ follow-redirects@1.5.10:
|
||||
dependencies:
|
||||
debug "=3.1.0"
|
||||
|
||||
follow-redirects@^1.14.0:
|
||||
version "1.14.5"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
|
||||
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
|
||||
|
||||
foreach@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
|
||||
@ -1732,12 +1810,12 @@ functional-red-black-tree@^1.0.1:
|
||||
resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||
|
||||
gas-price-oracle@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.npmjs.org/gas-price-oracle/-/gas-price-oracle-0.2.2.tgz#32c57a9aa6bc69152be96812880232efebfecbc6"
|
||||
integrity sha512-I4+rLbc7C1vgYXV+cYY0MKeqdZVna2hXpNfD2fcIvf/wIgvtIYmG9gsmhiaYGSgOE2RSPUs2xf/W4K2nJOoNuQ==
|
||||
gas-price-oracle@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/gas-price-oracle/-/gas-price-oracle-0.4.4.tgz#9b7e5583ed7126a68f9d230b9efbd9d75d864bad"
|
||||
integrity sha512-alAHLiZmPJ+GxKvujZZzEY8NRPqgGGHmDQUPFTa6HAMFB4LR/T6ShTDbqQzsdeWLPSw/j8/Gux0ZSC2AsPK+Hg==
|
||||
dependencies:
|
||||
axios "^0.19.2"
|
||||
axios "^0.21.2"
|
||||
bignumber.js "^9.0.0"
|
||||
|
||||
get-caller-file@^1.0.1:
|
||||
@ -2059,6 +2137,11 @@ invert-kv@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
|
||||
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
|
||||
|
||||
ip@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
@ -2883,6 +2966,11 @@ prepend-http@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
|
||||
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
|
||||
|
||||
printj@~1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
||||
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
|
||||
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
@ -3089,6 +3177,13 @@ rlp@^2.2.3:
|
||||
dependencies:
|
||||
bn.js "^4.11.1"
|
||||
|
||||
rlp@^2.2.4:
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf"
|
||||
integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==
|
||||
dependencies:
|
||||
bn.js "^5.2.0"
|
||||
|
||||
run-async@^2.2.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
|
||||
@ -3266,6 +3361,11 @@ slice-ansi@^4.0.0:
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
smart-buffer@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
|
||||
"snarkjs@git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5":
|
||||
version "0.1.20"
|
||||
resolved "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
||||
@ -3277,6 +3377,23 @@ slice-ansi@^4.0.0:
|
||||
keccak "^2.0.0"
|
||||
yargs "^12.0.5"
|
||||
|
||||
socks-proxy-agent@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
|
||||
integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
|
||||
dependencies:
|
||||
agent-base "^6.0.2"
|
||||
debug "^4.3.1"
|
||||
socks "^2.6.1"
|
||||
|
||||
socks@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
|
||||
integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==
|
||||
dependencies:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.1.0"
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
@ -3714,6 +3831,15 @@ web3-bzz@1.3.1:
|
||||
swarm-js "^0.1.40"
|
||||
underscore "1.9.1"
|
||||
|
||||
web3-bzz@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.1.tgz#8430eb3cbb69baaee4981d190b840748c37a9ec2"
|
||||
integrity sha512-JbnFNbRlwwHJZPtVuCxo7rC4U4OTg+mPsyhjgPQJJhS0a6Y54OgVWYk9UA/95HqbmTJwTtX329gJoSsseEfrng==
|
||||
dependencies:
|
||||
"@types/node" "^12.12.6"
|
||||
got "9.6.0"
|
||||
swarm-js "^0.1.40"
|
||||
|
||||
web3-core-helpers@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.1.tgz#ffd6f47c1b54a8523f00760a8d713f44d0f97e97"
|
||||
@ -3723,6 +3849,14 @@ web3-core-helpers@1.3.1:
|
||||
web3-eth-iban "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-core-helpers@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz#cb21047306871f4cf0fedfece7d47ea2aa96141b"
|
||||
integrity sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng==
|
||||
dependencies:
|
||||
web3-eth-iban "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-core-method@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.1.tgz#c1d8bf1e2104a8d625c99caf94218ad2dc948c92"
|
||||
@ -3735,6 +3869,17 @@ web3-core-method@1.3.1:
|
||||
web3-core-subscriptions "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-core-method@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.1.tgz#4ae91c639bf1da85ebfd8b99595da6a2235d7b98"
|
||||
integrity sha512-szH5KyIWIaULQDBdDvevQUCHV9lsExJ/oV0ePqK+w015D2SdMPMuhii0WB+HCePaksWO+rr/GAypvV9g2T3N+w==
|
||||
dependencies:
|
||||
"@ethersproject/transactions" "^5.0.0-beta.135"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-promievent "1.6.1"
|
||||
web3-core-subscriptions "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-core-promievent@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.1.tgz#b4da4b34cd9681e22fcda25994d7629280a1e046"
|
||||
@ -3742,6 +3887,13 @@ web3-core-promievent@1.3.1:
|
||||
dependencies:
|
||||
eventemitter3 "4.0.4"
|
||||
|
||||
web3-core-promievent@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.1.tgz#f650dea9361e2edf02691015b213fcc8ea499992"
|
||||
integrity sha512-byJ5s2MQxrWdXd27pWFmujfzsTZK4ik8rDgIV1RFDFc+rHZ2nZhq+VWk7t/Nkrj7EaVXncEgTdPEHc18nx+ocQ==
|
||||
dependencies:
|
||||
eventemitter3 "4.0.4"
|
||||
|
||||
web3-core-requestmanager@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.1.tgz#6dd2b5161ba778dfffe68994a4accff2decc54fe"
|
||||
@ -3754,6 +3906,17 @@ web3-core-requestmanager@1.3.1:
|
||||
web3-providers-ipc "1.3.1"
|
||||
web3-providers-ws "1.3.1"
|
||||
|
||||
web3-core-requestmanager@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.1.tgz#d9c08b0716c9cda546a0c02767b7e08deb04448a"
|
||||
integrity sha512-4y7etYEUtkfflyYVBfN1oJtCbVFNhNX1omlEYzezhTnPj3/dT7n+dhUXcqvIhx9iKA13unGfpFge80XNFfcB8A==
|
||||
dependencies:
|
||||
util "^0.12.0"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-providers-http "1.6.1"
|
||||
web3-providers-ipc "1.6.1"
|
||||
web3-providers-ws "1.6.1"
|
||||
|
||||
web3-core-subscriptions@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.1.tgz#be1103259f91b7fc7f4c6a867aa34dea70a636f7"
|
||||
@ -3763,6 +3926,14 @@ web3-core-subscriptions@1.3.1:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.3.1"
|
||||
|
||||
web3-core-subscriptions@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.1.tgz#4dfc1f74137354d4ac9eaa628aa916c5e2cc8741"
|
||||
integrity sha512-WZwxsYttIojyGQ5RqxuQcKg0IJdDCFpUe4EncS3QKZwxPqWzGmgyLwE0rm7tP+Ux1waJn5CUaaoSCBxWGSun1g==
|
||||
dependencies:
|
||||
eventemitter3 "4.0.4"
|
||||
web3-core-helpers "1.6.1"
|
||||
|
||||
web3-core@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-core/-/web3-core-1.3.1.tgz#fb0fc5d952a7f3d580a7e6155d2f28be064e64cb"
|
||||
@ -3776,6 +3947,19 @@ web3-core@1.3.1:
|
||||
web3-core-requestmanager "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-core@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.1.tgz#b41f08fdc9ea1082d15384a3d6fa93a47c3fc1b4"
|
||||
integrity sha512-m+b7UfYvU5cQUAh6NRfxRzH/5B3to1AdEQi1HIQt570cDWlObOOmoO9tY6iJnI5w4acxIO19LqjDMqEJGBYyRQ==
|
||||
dependencies:
|
||||
"@types/bn.js" "^4.11.5"
|
||||
"@types/node" "^12.12.6"
|
||||
bignumber.js "^9.0.0"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-core-requestmanager "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-abi@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.1.tgz#d60fe5f15c7a3a426c553fdaa4199d07f1ad899c"
|
||||
@ -3785,6 +3969,14 @@ web3-eth-abi@1.3.1:
|
||||
underscore "1.9.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-abi@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.1.tgz#15b937e3188570754d50bbac51a4bb0578600d1d"
|
||||
integrity sha512-svhYrAlXP9XQtV7poWKydwDJq2CaNLMtmKydNXoOBLcQec6yGMP+v20pgrxF2H6wyTK+Qy0E3/5ciPOqC/VuoQ==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "5.0.7"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-accounts@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.1.tgz#63b247461f1ae0ae46f9a5d5aa896ea80237143e"
|
||||
@ -3802,6 +3994,23 @@ web3-eth-accounts@1.3.1:
|
||||
web3-core-method "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-accounts@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.1.tgz#aeb0dfb52c4391773550569732975b471212583f"
|
||||
integrity sha512-rGn3jwnuOKwaQRu4SiShz0YAQ87aVDBKs4HO43+XTCI1q1Y1jn3NOsG3BW9ZHaOckev4+zEyxze/Bsh2oEk24w==
|
||||
dependencies:
|
||||
"@ethereumjs/common" "^2.5.0"
|
||||
"@ethereumjs/tx" "^3.3.2"
|
||||
crypto-browserify "3.12.0"
|
||||
eth-lib "0.2.8"
|
||||
ethereumjs-util "^7.0.10"
|
||||
scrypt-js "^3.0.1"
|
||||
uuid "3.3.2"
|
||||
web3-core "1.6.1"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-contract@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.1.tgz#05cb77bd2a671c5480897d20de487f3bae82e113"
|
||||
@ -3817,6 +4026,20 @@ web3-eth-contract@1.3.1:
|
||||
web3-eth-abi "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-contract@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.1.tgz#4b0a2c0b37015d70146e54c7cb3f035a58fbeec0"
|
||||
integrity sha512-GXqTe3mF6kpbOAakiNc7wtJ120/gpuKMTZjuGFKeeY8aobRLfbfgKzM9IpyqVZV2v5RLuGXDuurVN2KPgtu3hQ==
|
||||
dependencies:
|
||||
"@types/bn.js" "^4.11.5"
|
||||
web3-core "1.6.1"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-core-promievent "1.6.1"
|
||||
web3-core-subscriptions "1.6.1"
|
||||
web3-eth-abi "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-ens@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.1.tgz#ccfd621ddc1fecb44096bc8e60689499a9eb4421"
|
||||
@ -3832,6 +4055,20 @@ web3-eth-ens@1.3.1:
|
||||
web3-eth-contract "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-ens@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.1.tgz#801bd5fb5237377ec2ed8517a9fe4634f2269c7a"
|
||||
integrity sha512-ngprtbnoRgxg8s1wXt9nXpD3h1P+p7XnKXrp/8GdFI9uDmrbSQPRfzBw86jdZgOmy78hAnWmrHI6pBInmgi2qQ==
|
||||
dependencies:
|
||||
content-hash "^2.5.2"
|
||||
eth-ens-namehash "2.0.8"
|
||||
web3-core "1.6.1"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-promievent "1.6.1"
|
||||
web3-eth-abi "1.6.1"
|
||||
web3-eth-contract "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-iban@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.1.tgz#4351e1a658efa5f3218357f0a38d6d8cad82481e"
|
||||
@ -3840,6 +4077,14 @@ web3-eth-iban@1.3.1:
|
||||
bn.js "^4.11.9"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-iban@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz#20bbed75723e3e9ff98e624979629d26329462b6"
|
||||
integrity sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q==
|
||||
dependencies:
|
||||
bn.js "^4.11.9"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth-personal@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.1.tgz#cfe8af01588870d195dabf0a8d9e34956fb8856d"
|
||||
@ -3852,6 +4097,18 @@ web3-eth-personal@1.3.1:
|
||||
web3-net "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth-personal@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.1.tgz#9b524fb9f92b51163f46920ee2663d34a4897c8d"
|
||||
integrity sha512-ItsC89Ln02+irzJjK6ALcLrMZfbVUCqVbmb/ieDKJ+eLW3pNkBNwoUzaydh92d5NzxNZgNxuQWVdlFyYX2hkEw==
|
||||
dependencies:
|
||||
"@types/node" "^12.12.6"
|
||||
web3-core "1.6.1"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-net "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-eth@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.1.tgz#60ac4b58e5fd17b8dbbb8378abd63b02e8326727"
|
||||
@ -3871,6 +4128,24 @@ web3-eth@1.3.1:
|
||||
web3-net "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-eth@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.1.tgz#a25aba1ac213d872ecf3f81c7b4ab8072ecae224"
|
||||
integrity sha512-kOV1ZgCKypSo5BQyltRArS7ZC3bRpIKAxSgzl7pUFinUb/MxfbM9KGeNxUXoCfTSErcCQJaDjcS6bSre5EMKuQ==
|
||||
dependencies:
|
||||
web3-core "1.6.1"
|
||||
web3-core-helpers "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-core-subscriptions "1.6.1"
|
||||
web3-eth-abi "1.6.1"
|
||||
web3-eth-accounts "1.6.1"
|
||||
web3-eth-contract "1.6.1"
|
||||
web3-eth-ens "1.6.1"
|
||||
web3-eth-iban "1.6.1"
|
||||
web3-eth-personal "1.6.1"
|
||||
web3-net "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-net@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-net/-/web3-net-1.3.1.tgz#79374b1df37429b0839b83b0abc4440ac6181568"
|
||||
@ -3880,6 +4155,15 @@ web3-net@1.3.1:
|
||||
web3-core-method "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3-net@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.1.tgz#7a630a804ec9f81908ae52ccbb4ebbb9530b3906"
|
||||
integrity sha512-gpnqKEIwfUHh5ik7wsQFlCje1DfcmGv+Sk7LCh1hCqn++HEDQxJ/mZCrMo11ZZpZHCH7c87imdxTg96GJnRxDw==
|
||||
dependencies:
|
||||
web3-core "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
web3-providers-http@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.1.tgz#becbea61706b2fa52e15aca6fe519ee108a8fab9"
|
||||
@ -3888,6 +4172,20 @@ web3-providers-http@1.3.1:
|
||||
web3-core-helpers "1.3.1"
|
||||
xhr2-cookies "1.1.0"
|
||||
|
||||
web3-providers-http@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.1.tgz#b59b14eefef23b98c327806f5f566303a73bd435"
|
||||
integrity sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A==
|
||||
dependencies:
|
||||
web3-core-helpers "1.6.1"
|
||||
xhr2-cookies "1.1.0"
|
||||
|
||||
"web3-providers-http@file:./local_modules/web3-providers-http":
|
||||
version "1.6.1"
|
||||
dependencies:
|
||||
web3-core-helpers "1.6.1"
|
||||
xhr2-cookies "file:./../../AppData/Local/Yarn/Cache/v6/npm-web3-providers-http-1.6.1-6879cf8b-ee02-483d-9a46-76314494b334-1638895560210/node_modules/web3-providers-http/local_modules/xhr2-cookies"
|
||||
|
||||
web3-providers-ipc@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.1.tgz#3cb2572fc5286ab2f3117e0a2dce917816c3dedb"
|
||||
@ -3897,6 +4195,14 @@ web3-providers-ipc@1.3.1:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.3.1"
|
||||
|
||||
web3-providers-ipc@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.1.tgz#7ba460589d46896bb3d124288deed1b6a72d517e"
|
||||
integrity sha512-anyoIZlpMzwEQI4lwylTzDrHsVp20v0QUtSTp2B5jInBinmQtyCE7vnbX20jEQ4j5uPwfJabKNtoJsk6a3O4WQ==
|
||||
dependencies:
|
||||
oboe "2.1.5"
|
||||
web3-core-helpers "1.6.1"
|
||||
|
||||
web3-providers-ws@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.1.tgz#a70140811d138a1a5cf3f0c39d11887c8e341c83"
|
||||
@ -3907,6 +4213,15 @@ web3-providers-ws@1.3.1:
|
||||
web3-core-helpers "1.3.1"
|
||||
websocket "^1.0.32"
|
||||
|
||||
web3-providers-ws@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.1.tgz#f7ee71f158971102b865e99ea7911f483e0507e9"
|
||||
integrity sha512-FWMEFYb4rYFYRgSFBf/O1Ex4p/YKSlN+JydCtdlJwRimd89qm95CTfs4xGjCskwvXMjV2sarH+f1NPwJXicYpg==
|
||||
dependencies:
|
||||
eventemitter3 "4.0.4"
|
||||
web3-core-helpers "1.6.1"
|
||||
websocket "^1.0.32"
|
||||
|
||||
web3-shh@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.1.tgz#42294d684358c22aa48616cb9a3eb2e9c1e6362f"
|
||||
@ -3917,6 +4232,16 @@ web3-shh@1.3.1:
|
||||
web3-core-subscriptions "1.3.1"
|
||||
web3-net "1.3.1"
|
||||
|
||||
web3-shh@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.1.tgz#eebaab2e5e6be80fe2585c6c094fa10a03349ca7"
|
||||
integrity sha512-oP00HbAtybLCGlLOZUYXOdeB9xq88k2l0TtStvKBtmFqRt+zVk5TxEeuOnVPRxNhcA2Un8RUw6FtvgZlWStu9A==
|
||||
dependencies:
|
||||
web3-core "1.6.1"
|
||||
web3-core-method "1.6.1"
|
||||
web3-core-subscriptions "1.6.1"
|
||||
web3-net "1.6.1"
|
||||
|
||||
web3-utils@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.1.tgz#9aa880dd8c9463fe5c099107889f86a085370c2e"
|
||||
@ -3931,7 +4256,20 @@ web3-utils@1.3.1:
|
||||
underscore "1.9.1"
|
||||
utf8 "3.0.0"
|
||||
|
||||
web3@^1.2.11, web3@^1.2.8:
|
||||
web3-utils@1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca"
|
||||
integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w==
|
||||
dependencies:
|
||||
bn.js "^4.11.9"
|
||||
ethereum-bloom-filters "^1.0.6"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethjs-unit "0.1.6"
|
||||
number-to-bn "1.7.0"
|
||||
randombytes "^2.1.0"
|
||||
utf8 "3.0.0"
|
||||
|
||||
web3@^1.2.11:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/web3/-/web3-1.3.1.tgz#f780138c92ae3c42ea45e1a3c6ae8844e0aa5054"
|
||||
integrity sha512-lDJwOLSRWHYwhPy4h5TNgBRJ/lED7lWXyVOXHCHcEC8ai3coBNdgEXWBu/GGYbZMsS89EoUOJ14j3Ufi4dUkog==
|
||||
@ -3944,6 +4282,19 @@ web3@^1.2.11, web3@^1.2.8:
|
||||
web3-shh "1.3.1"
|
||||
web3-utils "1.3.1"
|
||||
|
||||
web3@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.1.tgz#c9e68fe7b3073adddf35393441f950ec69b92735"
|
||||
integrity sha512-c299lLiyb2/WOcxh7TinwvbATaMmrgNIeAzbLbmOKHI0LcwyfsB1eu2ReOIrfrCYDYRW2KAjYr7J7gHawqDNPQ==
|
||||
dependencies:
|
||||
web3-bzz "1.6.1"
|
||||
web3-core "1.6.1"
|
||||
web3-eth "1.6.1"
|
||||
web3-eth-personal "1.6.1"
|
||||
web3-net "1.6.1"
|
||||
web3-shh "1.6.1"
|
||||
web3-utils "1.6.1"
|
||||
|
||||
"websnark@git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d":
|
||||
version "0.0.4"
|
||||
resolved "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d"
|
||||
@ -4060,6 +4411,11 @@ xhr2-cookies@1.1.0:
|
||||
dependencies:
|
||||
cookiejar "^2.1.1"
|
||||
|
||||
"xhr2-cookies@file:./local_modules/web3-providers-http/local_modules/xhr2-cookies":
|
||||
version "1.1.0"
|
||||
dependencies:
|
||||
cookiejar "^2.1.1"
|
||||
|
||||
xhr@^2.0.4, xhr@^2.3.3:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d"
|
||||
|
Loading…
Reference in New Issue
Block a user