forked from tornadocash/tornado-cli
Fix gas issues: add correct estimation for relayer withdrawal, add L1 fee fetching for Optimism, correct gas price estimation
This commit is contained in:
parent
7243803b21
commit
ac0ccbb787
151
build/contracts/OptimismL1GasPriceOracle.json
Normal file
151
build/contracts/OptimismL1GasPriceOracle.json
Normal file
@ -0,0 +1,151 @@
|
||||
[
|
||||
{
|
||||
"inputs": [{ "internalType": "address", "name": "_owner", "type": "address" }],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "DecimalsUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "GasPriceUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "L1BaseFeeUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "OverheadUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" },
|
||||
{ "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "ScalarUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "gasPrice",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
|
||||
"name": "getL1Fee",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
|
||||
"name": "getL1GasUsed",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "l1BaseFee",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "overhead",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "scalar",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "_decimals", "type": "uint256" }],
|
||||
"name": "setDecimals",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "_gasPrice", "type": "uint256" }],
|
||||
"name": "setGasPrice",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "_baseFee", "type": "uint256" }],
|
||||
"name": "setL1BaseFee",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "_overhead", "type": "uint256" }],
|
||||
"name": "setOverhead",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "_scalar", "type": "uint256" }],
|
||||
"name": "setScalar",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
150
cli.js
150
cli.js
@ -11,6 +11,7 @@ const bigInt = snarkjs.bigInt;
|
||||
const merkleTree = require('@tornado/fixed-merkle-tree');
|
||||
const Web3 = require('web3');
|
||||
const Web3HttpProvider = require('@tornado/web3-providers-http');
|
||||
const { serialize } = require('@ethersproject/transactions');
|
||||
const buildGroth16 = require('@tornado/websnark/src/groth16');
|
||||
const websnarkUtils = require('@tornado/websnark/src/utils');
|
||||
const { toWei, fromWei, toBN, BN } = require('web3-utils');
|
||||
@ -32,7 +33,7 @@ let web3,
|
||||
tornadoContract,
|
||||
tornadoInstance,
|
||||
circuit,
|
||||
proving_key,
|
||||
provingKey,
|
||||
groth16,
|
||||
erc20,
|
||||
senderAccount,
|
||||
@ -40,13 +41,13 @@ let web3,
|
||||
netName,
|
||||
netSymbol,
|
||||
multiCall,
|
||||
userAction,
|
||||
subgraph;
|
||||
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, TOKEN_AMOUNT, PRIVATE_KEY;
|
||||
|
||||
/** Command state parameters */
|
||||
let preferenceSpeed = gasSpeedPreferences[0];
|
||||
let isTestRPC,
|
||||
eipGasSupport = false;
|
||||
let isTestRPC = false;
|
||||
let shouldPromptConfirmation = true;
|
||||
let doNotSubmitTx, privateRpc;
|
||||
/** ----------------------------------------- **/
|
||||
@ -178,9 +179,43 @@ async function estimateGas(from, to, nonce, encodedData, value = 0) {
|
||||
return bumped;
|
||||
}
|
||||
|
||||
async function fetchL1Fee({ gasPrice, gasLimit }) {
|
||||
const DUMMY_NONCE = '0x1111111111111111111111111111111111111111111111111111111111111111';
|
||||
|
||||
const DUMMY_WITHDRAW_DATA =
|
||||
'0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111';
|
||||
|
||||
if (netId === 10) {
|
||||
const ovmGasPriceOracleContractAddress = '0x420000000000000000000000000000000000000F';
|
||||
const optimismL1GasPriceOracleABI = require('./build/contracts/OptimismL1GasPriceOracle.json');
|
||||
const oracleInstance = new web3.eth.Contract(optimismL1GasPriceOracleABI, ovmGasPriceOracleContractAddress);
|
||||
|
||||
try {
|
||||
const tx = serialize({
|
||||
type: 0,
|
||||
gasLimit,
|
||||
chainId: netId,
|
||||
nonce: DUMMY_NONCE,
|
||||
data: DUMMY_WITHDRAW_DATA,
|
||||
gasPrice,
|
||||
to: tornadoProxyAddress
|
||||
});
|
||||
|
||||
const l1Fee = await oracleInstance.methods.getL1Fee(tx).call();
|
||||
|
||||
return l1Fee;
|
||||
} catch (err) {
|
||||
throw new Error('Error while fetching optimism L1 fee: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
async function generateTransaction(to, encodedData, value = 0) {
|
||||
const nonce = await web3.eth.getTransactionCount(senderAccount);
|
||||
let gasPrice = await fetchGasPrice();
|
||||
|
||||
let gasLimit;
|
||||
|
||||
if (encodedData) {
|
||||
@ -192,12 +227,16 @@ async function generateTransaction(to, encodedData, value = 0) {
|
||||
|
||||
const isNumRString = typeof value == 'string' || typeof value == 'number';
|
||||
const valueCost = isNumRString ? toBN(value) : value;
|
||||
const gasCosts = toBN(gasPrice).mul(toBN(gasLimit));
|
||||
|
||||
const additionalFees = userAction === 'withdrawal' ? await fetchL1Fee({ gasPrice, gasLimit }) : 0;
|
||||
const gasCosts = toBN(gasPrice).mul(toBN(gasLimit)).add(toBN(additionalFees));
|
||||
const totalCosts = valueCost.add(gasCosts);
|
||||
|
||||
/** Transaction details */
|
||||
console.log('Gas price: ', web3.utils.hexToNumber(gasPrice));
|
||||
console.log('Gas limit: ', web3.utils.hexToNumber(gasLimit));
|
||||
if (additionalFees != 0)
|
||||
console.log('Additional gas fees (like L1 data fee): ', rmDecimalBN(fromWei(additionalFees), 12), `${netSymbol}`);
|
||||
console.log('Transaction fee: ', rmDecimalBN(fromWei(gasCosts), 12), `${netSymbol}`);
|
||||
console.log('Transaction cost: ', rmDecimalBN(fromWei(totalCosts), 12), `${netSymbol}`);
|
||||
/** ----------------------------------------- **/
|
||||
@ -463,7 +502,7 @@ async function generateProof({ deposit, currency, amount, recipient, relayerAddr
|
||||
|
||||
console.log('Generating SNARK proof');
|
||||
console.time('Proof time');
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key);
|
||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, provingKey);
|
||||
const { proof } = websnarkUtils.toSolidityInput(proofData);
|
||||
console.timeEnd('Proof time');
|
||||
|
||||
@ -520,7 +559,7 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
||||
const merkleWithdrawalProof = await generateMerkleProof(deposit, currency, amount);
|
||||
|
||||
async function calculateDataForRelayer(gasLimit) {
|
||||
const { desiredFee: totalFee, feePercent: relayerFee } = calculateRelayerWithdrawFee({
|
||||
const { desiredFee: totalFee, feePercent: relayerFee } = await calculateRelayerWithdrawFee({
|
||||
currency,
|
||||
gasPrice,
|
||||
amount,
|
||||
@ -550,8 +589,9 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
||||
const { proof, args, totalFee, relayerFee } = await calculateDataForRelayer(realGasLimit);
|
||||
|
||||
console.log('Sending withdraw transaction through relay');
|
||||
|
||||
const gasCosts = toBN(gasPrice).mul(toBN(realGasLimit));
|
||||
const l1Fee = await fetchL1Fee({ gasPrice, gasLimit: realGasLimit });
|
||||
console.log(l1Fee);
|
||||
const gasCosts = toBN(gasPrice).mul(toBN(realGasLimit)).add(toBN(l1Fee));
|
||||
|
||||
/** Relayer fee details **/
|
||||
console.log('Transaction fee: ', rmDecimalBN(fromWei(gasCosts), 12), `${netSymbol}`);
|
||||
@ -864,37 +904,31 @@ function getCurrentNetworkSymbol() {
|
||||
}
|
||||
}
|
||||
|
||||
function gasPricesETH(value = 80) {
|
||||
const tenPercent = (Number(value) * 5) / 100;
|
||||
const max = Math.max(tenPercent, 3);
|
||||
const bumped = Math.floor(Number(value) + max);
|
||||
return toHex(toWei(bumped.toString(), 'gwei'));
|
||||
}
|
||||
|
||||
function gasPrices(value = 5) {
|
||||
return toHex(toWei(value.toString(), 'gwei'));
|
||||
}
|
||||
|
||||
async function fetchGasPrice() {
|
||||
try {
|
||||
/** Gas preferences **/
|
||||
console.log('Gas speed preference: ', preferenceSpeed);
|
||||
/** ----------------------------------------------- **/
|
||||
|
||||
try {
|
||||
const isLegacy = !eipGasSupport;
|
||||
const oracleOptions = { chainId: netId, defaultRpc: web3.currentProvider.host };
|
||||
const oracle = new GasPriceOracle(oracleOptions);
|
||||
const gas = await oracle.gasPrices({ isLegacy });
|
||||
// Extra bump estimated gas price for Polygon and Goerli
|
||||
const bumpPercent = netId === 137 || netId === 5 ? 30 : 10;
|
||||
|
||||
if (netId === 1) {
|
||||
return gasPricesETH(gas[preferenceSpeed]);
|
||||
} else {
|
||||
return gasPrices(gas[preferenceSpeed]);
|
||||
}
|
||||
try {
|
||||
const oracleOptions = {
|
||||
chainId: netId,
|
||||
defaultRpc: web3.currentProvider.host,
|
||||
minPriority: netId === 1 ? 3 : 0.05,
|
||||
percentile: 5,
|
||||
blocksCount: 20
|
||||
};
|
||||
const oracle = new GasPriceOracle(oracleOptions);
|
||||
const { maxFeePerGas, gasPrice } = await oracle.getTxGasParams({ legacySpeed: preferenceSpeed, bumpPercent });
|
||||
|
||||
return maxFeePerGas || gasPrice;
|
||||
} catch (e) {
|
||||
const wei = await web3.eth.getGasPrice();
|
||||
return wei / web3.utils.unitMap.gwei;
|
||||
const wei = toBN(await web3.eth.getGasPrice());
|
||||
const bumped = wei.add(wei.mul(toBN(bumpPercent)).div(toBN(100)));
|
||||
return toHex(bumped);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Method fetchGasPrice has error ${err.message}`);
|
||||
@ -936,13 +970,26 @@ async function estimateWithdrawGasLimit({ relayer, proof, callArgs }) {
|
||||
return gasLimit;
|
||||
}
|
||||
|
||||
function calculateRelayerWithdrawFee({ currency, gasPrice, amount, refund, ethPrices, relayerServiceFee, decimals, gasLimit }) {
|
||||
async function calculateRelayerWithdrawFee({
|
||||
currency,
|
||||
gasPrice,
|
||||
amount,
|
||||
refund,
|
||||
ethPrices,
|
||||
relayerServiceFee,
|
||||
decimals,
|
||||
gasLimit
|
||||
}) {
|
||||
const decimalsPoint =
|
||||
Math.floor(relayerServiceFee) === Number(relayerServiceFee) ? 0 : relayerServiceFee.toString().split('.')[1].length;
|
||||
const roundDecimal = 10 ** decimalsPoint;
|
||||
const total = toBN(fromDecimals({ amount, decimals }));
|
||||
const feePercent = total.mul(toBN(relayerServiceFee * roundDecimal)).div(toBN(roundDecimal * 100));
|
||||
const expense = toBN(gasPrice).mul(toBN(gasLimit || getHardcodedWithdrawGasLimit(netId)));
|
||||
const l1Fee = await fetchL1Fee({ gasPrice, gasLimit });
|
||||
const expense = toBN(gasPrice)
|
||||
.mul(toBN(gasLimit || getHardcodedWithdrawGasLimit(netId)))
|
||||
.add(toBN(l1Fee));
|
||||
|
||||
let desiredFee;
|
||||
switch (currency) {
|
||||
case netSymbol.toLowerCase(): {
|
||||
@ -1010,7 +1057,7 @@ function filterZeroEvents(events) {
|
||||
|
||||
function loadCachedEvents({ type, currency, amount }) {
|
||||
try {
|
||||
const module = require(`./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`);
|
||||
const module = require(`./cache/${netName.toLowerCase()}/${type}s_${currency.toLowerCase()}_${amount}.json`);
|
||||
|
||||
if (module) {
|
||||
const events = module;
|
||||
@ -1042,11 +1089,13 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
console.log('Fetching', amount, currency.toUpperCase(), type, 'events for', netName, 'network');
|
||||
|
||||
async function updateCache(fetchedEvents) {
|
||||
if (type === 'deposit') fetchedEvents.sort((firstLeaf, secondLeaf) => firstLeaf.leafIndex - secondLeaf.leafIndex);
|
||||
|
||||
try {
|
||||
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`;
|
||||
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency.toLowerCase()}_${amount}.json`;
|
||||
const localEvents = await initJson(fileName);
|
||||
const events = filterZeroEvents(localEvents).concat(fetchedEvents);
|
||||
await fs.writeFileSync(fileName, JSON.stringify(events, null, 2), 'utf8');
|
||||
fs.writeFileSync(fileName, JSON.stringify(events, null, 2), 'utf8');
|
||||
} catch (error) {
|
||||
throw new Error('Writing cache file failed:', error);
|
||||
}
|
||||
@ -1056,7 +1105,7 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
* Adds an zero (empty) event to the end of the events list
|
||||
* If tornado transactions on the selected currency/amount are rare and the last one was much earlier than the current block,
|
||||
* it helps to quickly synchronize the events tree
|
||||
* @param blockNumber Latest block number on selected chain
|
||||
* @param {number} blockNumber Latest block number on selected chain
|
||||
*/
|
||||
async function addZeroEvent(blockNumber) {
|
||||
const zeroEvent = { blockNumber, transactionHash: null };
|
||||
@ -1068,7 +1117,7 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
async function syncEvents() {
|
||||
try {
|
||||
let targetBlock = await web3.eth.getBlockNumber();
|
||||
let chunks = 1000;
|
||||
let chunks = 10000;
|
||||
console.log('Querying latest events from RPC');
|
||||
|
||||
for (let i = startBlock; i < targetBlock; i += chunks) {
|
||||
@ -1138,8 +1187,6 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
await fetchWeb3Events(i);
|
||||
await updateCache(fetchedEvents);
|
||||
}
|
||||
|
||||
await addZeroEvent(targetBlock);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new Error('Error while updating cache');
|
||||
@ -1158,9 +1205,10 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
async function queryLatestTimestamp() {
|
||||
try {
|
||||
const variables = {
|
||||
currency: currency.toString(),
|
||||
amount: amount.toString()
|
||||
currency: currency.toString().toLowerCase(),
|
||||
amount: amount.toString().toLowerCase()
|
||||
};
|
||||
console.log(variables);
|
||||
if (type === 'deposit') {
|
||||
const query = {
|
||||
query: `
|
||||
@ -1201,11 +1249,12 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
async function queryFromGraph(timestamp) {
|
||||
try {
|
||||
const variables = {
|
||||
currency: currency.toString(),
|
||||
amount: amount.toString(),
|
||||
currency: currency.toString().toLowerCase(),
|
||||
amount: amount.toString().toLowerCase(),
|
||||
timestamp: timestamp
|
||||
};
|
||||
if (type === 'deposit') {
|
||||
console.log(variables);
|
||||
const query = {
|
||||
query: `
|
||||
query($currency: String, $amount: String, $timestamp: Int){
|
||||
@ -1228,7 +1277,7 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
transactionHash,
|
||||
commitment,
|
||||
leafIndex: Number(index),
|
||||
timestamp
|
||||
timestamp: Number(timestamp)
|
||||
};
|
||||
});
|
||||
return mapResult;
|
||||
@ -1299,18 +1348,20 @@ async function fetchEvents({ type, currency, amount, filterEvents }) {
|
||||
}
|
||||
await fetchGraphEvents();
|
||||
}
|
||||
if (!privateRpc && subgraph && !isTestRPC) {
|
||||
if (!privateRpc && !subgraph && !isTestRPC) {
|
||||
await syncGraphEvents();
|
||||
} else {
|
||||
await syncEvents();
|
||||
}
|
||||
await addZeroEvent(await web3.eth.getBlockNumber());
|
||||
|
||||
async function loadUpdatedEvents() {
|
||||
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`;
|
||||
// Don't use loadCachedEvents function, because we need to check zero event block (to which block we updated)
|
||||
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency.toLowerCase()}_${amount}.json`;
|
||||
const updatedEvents = await initJson(fileName);
|
||||
const updatedBlock = updatedEvents[updatedEvents.length - 1].blockNumber;
|
||||
console.log('Cache updated for Tornado', type, amount, currency, 'instance to block', updatedBlock, 'successfully');
|
||||
console.log(`Total ${type}s:`, updatedEvents.length);
|
||||
console.log(`Total ${type}s:`, updatedEvents.length - 1);
|
||||
return updatedEvents;
|
||||
}
|
||||
const events = await loadUpdatedEvents();
|
||||
@ -1510,7 +1561,7 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', balanceC
|
||||
contractJson = require('./build/contracts/TornadoProxy.abi.json');
|
||||
instanceJson = require('./build/contracts/Instance.abi.json');
|
||||
circuit = require('./build/circuits/tornado.json');
|
||||
proving_key = fs.readFileSync('build/circuits/tornadoProvingKey.bin').buffer;
|
||||
provingKey = fs.readFileSync('build/circuits/tornadoProvingKey.bin').buffer;
|
||||
MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT || 20;
|
||||
ETH_AMOUNT = process.env.ETH_AMOUNT;
|
||||
TOKEN_AMOUNT = process.env.TOKEN_AMOUNT;
|
||||
@ -1642,6 +1693,7 @@ async function main() {
|
||||
statePreferences(program);
|
||||
|
||||
const { currency, amount, netId, deposit } = parseNote(noteString);
|
||||
userAction = 'withdrawal';
|
||||
|
||||
await init({
|
||||
rpc: program.rpc,
|
||||
|
@ -1,47 +0,0 @@
|
||||
# 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
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
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;
|
@ -1,4 +0,0 @@
|
||||
node_modules
|
||||
yarn-error.log
|
||||
.idea
|
||||
!wallaby.js
|
@ -1,4 +0,0 @@
|
||||
*
|
||||
.idea
|
||||
!dist/*
|
||||
!package.json
|
@ -1,30 +0,0 @@
|
||||
# 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
|
@ -1,8 +0,0 @@
|
||||
export declare class SecurityError extends Error {
|
||||
}
|
||||
export declare class InvalidStateError extends Error {
|
||||
}
|
||||
export declare class NetworkError extends Error {
|
||||
}
|
||||
export declare class SyntaxError extends Error {
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var SecurityError = /** @class */ (function (_super) {
|
||||
__extends(SecurityError, _super);
|
||||
function SecurityError() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return SecurityError;
|
||||
}(Error));
|
||||
exports.SecurityError = SecurityError;
|
||||
var InvalidStateError = /** @class */ (function (_super) {
|
||||
__extends(InvalidStateError, _super);
|
||||
function InvalidStateError() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return InvalidStateError;
|
||||
}(Error));
|
||||
exports.InvalidStateError = InvalidStateError;
|
||||
var NetworkError = /** @class */ (function (_super) {
|
||||
__extends(NetworkError, _super);
|
||||
function NetworkError() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return NetworkError;
|
||||
}(Error));
|
||||
exports.NetworkError = NetworkError;
|
||||
var SyntaxError = /** @class */ (function (_super) {
|
||||
__extends(SyntaxError, _super);
|
||||
function SyntaxError() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return SyntaxError;
|
||||
}(Error));
|
||||
exports.SyntaxError = SyntaxError;
|
||||
//# sourceMappingURL=errors.js.map
|
@ -1 +0,0 @@
|
||||
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../errors.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;IAAmC,iCAAK;IAAxC;;IAA0C,CAAC;IAAD,oBAAC;AAAD,CAAC,AAA3C,CAAmC,KAAK,GAAG;AAA9B,sCAAa;AAC1B;IAAuC,qCAAK;IAA5C;;IAA8C,CAAC;IAAD,wBAAC;AAAD,CAAC,AAA/C,CAAuC,KAAK,GAAG;AAAlC,8CAAiB;AAC9B;IAAkC,gCAAK;IAAvC;;IAAyC,CAAC;IAAD,mBAAC;AAAD,CAAC,AAA1C,CAAkC,KAAK,GAAG;AAA7B,oCAAY;AACzB;IAAiC,+BAAK;IAAtC;;IAAwC,CAAC;IAAD,kBAAC;AAAD,CAAC,AAAzC,CAAiC,KAAK,GAAG;AAA5B,kCAAW"}
|
@ -1,2 +0,0 @@
|
||||
export * from './xml-http-request';
|
||||
export { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
@ -1,9 +0,0 @@
|
||||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__export(require("./xml-http-request"));
|
||||
var xml_http_request_event_target_1 = require("./xml-http-request-event-target");
|
||||
exports.XMLHttpRequestEventTarget = xml_http_request_event_target_1.XMLHttpRequestEventTarget;
|
||||
//# sourceMappingURL=index.js.map
|
@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;AAAA,wCAAmC;AACnC,iFAA4E;AAAnE,oEAAA,yBAAyB,CAAA"}
|
@ -1,11 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ProgressEvent = /** @class */ (function () {
|
||||
function ProgressEvent(type) {
|
||||
this.type = type;
|
||||
this.bubbles = false;
|
||||
this.cancelable = false;
|
||||
this.loaded = 0;
|
||||
this.lengthComputable = false;
|
||||
this.total = 0;
|
||||
}
|
||||
return ProgressEvent;
|
||||
}());
|
||||
exports.ProgressEvent = ProgressEvent;
|
||||
//# sourceMappingURL=progress-event.js.map
|
@ -1 +0,0 @@
|
||||
{"version":3,"file":"progress-event.js","sourceRoot":"","sources":["../progress-event.ts"],"names":[],"mappings":";;AAEA;IAQC,uBAAoB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAPhC,YAAO,GAAG,KAAK,CAAC;QAChB,eAAU,GAAG,KAAK,CAAC;QAEnB,WAAM,GAAG,CAAC,CAAC;QACX,qBAAgB,GAAG,KAAK,CAAC;QACzB,UAAK,GAAG,CAAC,CAAC;IAEyB,CAAC;IACrC,oBAAC;AAAD,CAAC,AATD,IASC;AATY,sCAAa"}
|
19
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-event-target.d.ts
vendored
19
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-event-target.d.ts
vendored
@ -1,19 +0,0 @@
|
||||
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;
|
||||
}
|
41
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-event-target.js
vendored
41
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-event-target.js
vendored
@ -1,41 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var XMLHttpRequestEventTarget = /** @class */ (function () {
|
||||
function XMLHttpRequestEventTarget() {
|
||||
this.listeners = {};
|
||||
}
|
||||
XMLHttpRequestEventTarget.prototype.addEventListener = function (eventType, listener) {
|
||||
eventType = eventType.toLowerCase();
|
||||
this.listeners[eventType] = this.listeners[eventType] || [];
|
||||
this.listeners[eventType].push(listener.handleEvent || listener);
|
||||
};
|
||||
XMLHttpRequestEventTarget.prototype.removeEventListener = function (eventType, listener) {
|
||||
eventType = eventType.toLowerCase();
|
||||
if (!this.listeners[eventType]) {
|
||||
return;
|
||||
}
|
||||
var index = this.listeners[eventType].indexOf(listener.handleEvent || listener);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
this.listeners[eventType].splice(index, 1);
|
||||
};
|
||||
XMLHttpRequestEventTarget.prototype.dispatchEvent = function (event) {
|
||||
var eventType = event.type.toLowerCase();
|
||||
event.target = this; // TODO: set event.currentTarget?
|
||||
if (this.listeners[eventType]) {
|
||||
for (var _i = 0, _a = this.listeners[eventType]; _i < _a.length; _i++) {
|
||||
var listener_1 = _a[_i];
|
||||
listener_1.call(this, event);
|
||||
}
|
||||
}
|
||||
var listener = this["on" + eventType];
|
||||
if (listener) {
|
||||
listener.call(this, event);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return XMLHttpRequestEventTarget;
|
||||
}());
|
||||
exports.XMLHttpRequestEventTarget = XMLHttpRequestEventTarget;
|
||||
//# sourceMappingURL=xml-http-request-event-target.js.map
|
@ -1 +0,0 @@
|
||||
{"version":3,"file":"xml-http-request-event-target.js","sourceRoot":"","sources":["../xml-http-request-event-target.ts"],"names":[],"mappings":";;AAMA;IAAA;QASS,cAAS,GAAmD,EAAE,CAAC;IAiCxE,CAAC;IA/BA,oDAAgB,GAAhB,UAAiB,SAAiB,EAAE,QAAqD;QACxF,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC5D,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAE,QAAwC,CAAC,WAAW,IAAK,QAAkC,CAAC,CAAC;IAC9H,CAAC;IACD,uDAAmB,GAAnB,UAAoB,SAAiB,EAAE,QAAqD;QAC3F,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACpC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAAC,MAAM,CAAC;QAAC,CAAC;QAE3C,IAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAE,QAAwC,CAAC,WAAW,IAAK,QAAkC,CAAC,CAAC;QAC9I,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YAAC,MAAM,CAAC;QAAC,CAAC;QAE1B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,iDAAa,GAAb,UAAc,KAAoB;QACjC,IAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3C,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,iCAAiC;QAEtD,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/B,GAAG,CAAC,CAAiB,UAAyB,EAAzB,KAAA,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAzB,cAAyB,EAAzB,IAAyB;gBAAzC,IAAI,UAAQ,SAAA;gBAChB,UAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;aAC3B;QACF,CAAC;QAED,IAAM,QAAQ,GAAG,IAAI,CAAC,OAAK,SAAW,CAAC,CAAC;QACxC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC;IACb,CAAC;IACF,gCAAC;AAAD,CAAC,AA1CD,IA0CC;AA1CY,8DAAyB"}
|
12
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.d.ts
vendored
12
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.d.ts
vendored
@ -1,12 +0,0 @@
|
||||
/// <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;
|
||||
}
|
78
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.js
vendored
78
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.js
vendored
@ -1,78 +0,0 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var xml_http_request_event_target_1 = require("./xml-http-request-event-target");
|
||||
var XMLHttpRequestUpload = /** @class */ (function (_super) {
|
||||
__extends(XMLHttpRequestUpload, _super);
|
||||
function XMLHttpRequestUpload() {
|
||||
var _this = _super.call(this) || this;
|
||||
_this._contentType = null;
|
||||
_this._body = null;
|
||||
_this._reset();
|
||||
return _this;
|
||||
}
|
||||
XMLHttpRequestUpload.prototype._reset = function () {
|
||||
this._contentType = null;
|
||||
this._body = null;
|
||||
};
|
||||
XMLHttpRequestUpload.prototype._setData = function (data) {
|
||||
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) {
|
||||
var body = Buffer.alloc(data.byteLength);
|
||||
var view = new Uint8Array(data);
|
||||
for (var i = 0; i < data.byteLength; i++) {
|
||||
body[i] = view[i];
|
||||
}
|
||||
this._body = body;
|
||||
}
|
||||
else if (data.buffer && data.buffer instanceof ArrayBuffer) {
|
||||
var body = Buffer.alloc(data.byteLength);
|
||||
var offset = data.byteOffset;
|
||||
var view = new Uint8Array(data.buffer);
|
||||
for (var i = 0; i < data.byteLength; i++) {
|
||||
body[i] = view[i + offset];
|
||||
}
|
||||
this._body = body;
|
||||
}
|
||||
else {
|
||||
throw new Error("Unsupported send() data " + data);
|
||||
}
|
||||
};
|
||||
XMLHttpRequestUpload.prototype._finalizeHeaders = function (headers, loweredHeaders) {
|
||||
if (this._contentType && !loweredHeaders['content-type']) {
|
||||
headers['Content-Type'] = this._contentType;
|
||||
}
|
||||
if (this._body) {
|
||||
headers['Content-Length'] = this._body.length.toString();
|
||||
}
|
||||
};
|
||||
XMLHttpRequestUpload.prototype._startUpload = function (request) {
|
||||
if (this._body) {
|
||||
request.write(this._body);
|
||||
}
|
||||
request.end();
|
||||
};
|
||||
return XMLHttpRequestUpload;
|
||||
}(xml_http_request_event_target_1.XMLHttpRequestEventTarget));
|
||||
exports.XMLHttpRequestUpload = XMLHttpRequestUpload;
|
||||
//# sourceMappingURL=xml-http-request-upload.js.map
|
1
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.js.map
vendored
1
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request-upload.js.map
vendored
@ -1 +0,0 @@
|
||||
{"version":3,"file":"xml-http-request-upload.js","sourceRoot":"","sources":["../xml-http-request-upload.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iFAA4E;AAG5E;IAA0C,wCAAyB;IAIlE;QAAA,YACC,iBAAO,SAEP;QANO,kBAAY,GAAkB,IAAI,CAAC;QACnC,WAAK,GAAG,IAAI,CAAC;QAIpB,KAAI,CAAC,MAAM,EAAE,CAAC;;IACf,CAAC;IAED,qCAAM,GAAN;QACC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,uCAAQ,GAAR,UAAS,IAAsD;QAC9D,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC;YAAC,MAAM,CAAC;QAAC,CAAC;QAE7B,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;YAC9B,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;gBACvB,IAAI,CAAC,YAAY,GAAG,0BAA0B,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACnB,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC;YACxC,IAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;YAClC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YAChE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACnB,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,YAAY,WAAW,CAAC,CAAC,CAAC;YAC9D,IAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;YAC/B,IAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAAC,CAAC;YACzE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACnB,CAAC;QAAC,IAAI,CAAC,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,6BAA2B,IAAM,CAAC,CAAC;QACpD,CAAC;IACF,CAAC;IAED,+CAAgB,GAAhB,UAAiB,OAAe,EAAE,cAAsB;QACvD,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;QAC7C,CAAC;QACD,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC1D,CAAC;IACF,CAAC;IAED,2CAAY,GAAZ,UAAa,OAAsB;QAClC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,EAAE,CAAC;IACf,CAAC;IACF,2BAAC;AAAD,CAAC,AArDD,CAA0C,yDAAyB,GAqDlE;AArDY,oDAAoB"}
|
102
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.d.ts
vendored
102
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.d.ts
vendored
@ -1,102 +0,0 @@
|
||||
/// <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();
|
||||
}
|
@ -1,448 +0,0 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var http = require("http");
|
||||
var https = require("https");
|
||||
var url = require("url");
|
||||
var progress_event_1 = require("./progress-event");
|
||||
var errors_1 = require("./errors");
|
||||
var xml_http_request_event_target_1 = require("./xml-http-request-event-target");
|
||||
var xml_http_request_upload_1 = require("./xml-http-request-upload");
|
||||
var Cookie = require("cookiejar");
|
||||
var XMLHttpRequest = /** @class */ (function (_super) {
|
||||
__extends(XMLHttpRequest, _super);
|
||||
function XMLHttpRequest(options) {
|
||||
if (options === void 0) { options = {}; }
|
||||
var _this = _super.call(this) || this;
|
||||
_this.UNSENT = XMLHttpRequest.UNSENT;
|
||||
_this.OPENED = XMLHttpRequest.OPENED;
|
||||
_this.HEADERS_RECEIVED = XMLHttpRequest.HEADERS_RECEIVED;
|
||||
_this.LOADING = XMLHttpRequest.LOADING;
|
||||
_this.DONE = XMLHttpRequest.DONE;
|
||||
_this.onreadystatechange = null;
|
||||
_this.readyState = XMLHttpRequest.UNSENT;
|
||||
_this.response = null;
|
||||
_this.responseText = '';
|
||||
_this.responseType = '';
|
||||
_this.status = 0; // TODO: UNSENT?
|
||||
_this.statusText = '';
|
||||
_this.timeout = 0;
|
||||
_this.upload = new xml_http_request_upload_1.XMLHttpRequestUpload();
|
||||
_this.responseUrl = '';
|
||||
_this.withCredentials = false;
|
||||
_this._method = null;
|
||||
_this._url = null;
|
||||
_this._sync = false;
|
||||
_this._headers = {};
|
||||
_this._loweredHeaders = {};
|
||||
_this._mimeOverride = null; // TODO: is type right?
|
||||
_this._request = null;
|
||||
_this._response = null;
|
||||
_this._responseParts = null;
|
||||
_this._responseHeaders = null;
|
||||
_this._aborting = null; // TODO: type?
|
||||
_this._error = null; // TODO: type?
|
||||
_this._loadedBytes = 0;
|
||||
_this._totalBytes = 0;
|
||||
_this._lengthComputable = false;
|
||||
_this._restrictedMethods = { CONNECT: true, TRACE: true, TRACK: true };
|
||||
_this._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
|
||||
};
|
||||
_this._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/
|
||||
_this._userAgent = "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
|
||||
_this._anonymous = options.anon || false;
|
||||
return _this;
|
||||
}
|
||||
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
|
||||
if (async === void 0) { async = true; }
|
||||
method = method.toUpperCase();
|
||||
if (this._restrictedMethods[method]) {
|
||||
throw new XMLHttpRequest.SecurityError("HTTP method " + method + " is not allowed in XHR");
|
||||
}
|
||||
;
|
||||
var 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;
|
||||
};
|
||||
XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
|
||||
if (this.readyState !== XMLHttpRequest.OPENED) {
|
||||
throw new XMLHttpRequest.InvalidStateError('XHR readyState must be OPENED');
|
||||
}
|
||||
var 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;
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.prototype.send = function (data) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.prototype.abort = function () {
|
||||
if (this._request == null) {
|
||||
return;
|
||||
}
|
||||
this._request.abort();
|
||||
this._setError();
|
||||
this._dispatchProgress('abort');
|
||||
this._dispatchProgress('loadend');
|
||||
};
|
||||
XMLHttpRequest.prototype.getResponseHeader = function (name) {
|
||||
if (this._responseHeaders == null || name == null) {
|
||||
return null;
|
||||
}
|
||||
var loweredName = name.toLowerCase();
|
||||
return this._responseHeaders.hasOwnProperty(loweredName)
|
||||
? this._responseHeaders[name.toLowerCase()]
|
||||
: null;
|
||||
};
|
||||
XMLHttpRequest.prototype.getAllResponseHeaders = function () {
|
||||
var _this = this;
|
||||
if (this._responseHeaders == null) {
|
||||
return '';
|
||||
}
|
||||
return Object.keys(this._responseHeaders).map(function (key) { return key + ": " + _this._responseHeaders[key]; }).join('\r\n');
|
||||
};
|
||||
XMLHttpRequest.prototype.overrideMimeType = function (mimeType) {
|
||||
if (this.readyState === XMLHttpRequest.LOADING || this.readyState === XMLHttpRequest.DONE) {
|
||||
throw new XMLHttpRequest.InvalidStateError('overrideMimeType() not allowed in LOADING or DONE');
|
||||
}
|
||||
this._mimeOverride = mimeType.toLowerCase();
|
||||
};
|
||||
XMLHttpRequest.prototype.nodejsSet = function (options) {
|
||||
this.nodejsHttpAgent = options.httpAgent || this.nodejsHttpAgent;
|
||||
this.nodejsHttpsAgent = options.httpsAgent || this.nodejsHttpsAgent;
|
||||
if (options.hasOwnProperty('baseUrl')) {
|
||||
if (options.baseUrl != null) {
|
||||
var parsedUrl = url.parse(options.baseUrl, false, true);
|
||||
if (!parsedUrl.protocol) {
|
||||
throw new XMLHttpRequest.SyntaxError("baseUrl must be an absolute URL");
|
||||
}
|
||||
}
|
||||
this.nodejsBaseUrl = options.baseUrl;
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.nodejsSet = function (options) {
|
||||
XMLHttpRequest.prototype.nodejsSet(options);
|
||||
};
|
||||
XMLHttpRequest.prototype._setReadyState = function (readyState) {
|
||||
this.readyState = readyState;
|
||||
this.dispatchEvent(new progress_event_1.ProgressEvent('readystatechange'));
|
||||
};
|
||||
XMLHttpRequest.prototype._sendFile = function (data) {
|
||||
// TODO
|
||||
throw new Error('Protocol file: not implemented');
|
||||
};
|
||||
XMLHttpRequest.prototype._sendHttp = function (data) {
|
||||
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();
|
||||
};
|
||||
XMLHttpRequest.prototype._sendHxxpRequest = function () {
|
||||
var _this = this;
|
||||
if (this.withCredentials) {
|
||||
var cookie = XMLHttpRequest.cookieJar
|
||||
.getCookies(Cookie.CookieAccessInfo(this._url.hostname, this._url.pathname, this._url.protocol === 'https:')).toValueString();
|
||||
this._headers.cookie = this._headers.cookie2 = cookie;
|
||||
}
|
||||
var _a = this._url.protocol === 'http:' ? [http, this.nodejsHttpAgent] : [https, this.nodejsHttpsAgent], hxxp = _a[0], agent = _a[1];
|
||||
var requestMethod = hxxp.request.bind(hxxp);
|
||||
var 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: agent
|
||||
});
|
||||
this._request = request;
|
||||
if (this.timeout) {
|
||||
request.setTimeout(this.timeout, function () { return _this._onHttpTimeout(request); });
|
||||
}
|
||||
request.on('response', function (response) { return _this._onHttpResponse(request, response); });
|
||||
request.on('error', function (error) { return _this._onHttpRequestError(request, error); });
|
||||
this.upload._startUpload(request);
|
||||
if (this._request === request) {
|
||||
this._dispatchProgress('loadstart');
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.prototype._finalizeHeaders = function () {
|
||||
this._headers = __assign({}, 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);
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpResponse = function (request, response) {
|
||||
var _this = this;
|
||||
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', function (data) { return _this._onHttpResponseData(response, data); });
|
||||
this._response.on('end', function () { return _this._onHttpResponseEnd(response); });
|
||||
this._response.on('close', function () { return _this._onHttpResponseClose(response); });
|
||||
this.responseUrl = this._url.href.split('#')[0];
|
||||
this.status = response.statusCode;
|
||||
this.statusText = http.STATUS_CODES[this.status];
|
||||
this._parseResponseHeaders(response);
|
||||
var lengthString = this._responseHeaders['content-length'] || '';
|
||||
this._totalBytes = +lengthString;
|
||||
this._lengthComputable = !!lengthString;
|
||||
this._setReadyState(XMLHttpRequest.HEADERS_RECEIVED);
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpResponseData = function (response, data) {
|
||||
if (this._response !== response) {
|
||||
return;
|
||||
}
|
||||
this._responseParts.push(Buffer.from(data));
|
||||
this._loadedBytes += data.length;
|
||||
if (this.readyState !== XMLHttpRequest.LOADING) {
|
||||
this._setReadyState(XMLHttpRequest.LOADING);
|
||||
}
|
||||
this._dispatchProgress('progress');
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpResponseEnd = function (response) {
|
||||
if (this._response !== response) {
|
||||
return;
|
||||
}
|
||||
this._parseResponse();
|
||||
this._request = null;
|
||||
this._response = null;
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
this._dispatchProgress('load');
|
||||
this._dispatchProgress('loadend');
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpResponseClose = function (response) {
|
||||
if (this._response !== response) {
|
||||
return;
|
||||
}
|
||||
var request = this._request;
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
this._dispatchProgress('error');
|
||||
this._dispatchProgress('loadend');
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpTimeout = function (request) {
|
||||
if (this._request !== request) {
|
||||
return;
|
||||
}
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
this._dispatchProgress('timeout');
|
||||
this._dispatchProgress('loadend');
|
||||
};
|
||||
XMLHttpRequest.prototype._onHttpRequestError = function (request, error) {
|
||||
if (this._request !== request) {
|
||||
return;
|
||||
}
|
||||
this._setError();
|
||||
request.abort();
|
||||
this._setReadyState(XMLHttpRequest.DONE);
|
||||
this._dispatchProgress('error');
|
||||
this._dispatchProgress('loadend');
|
||||
};
|
||||
XMLHttpRequest.prototype._dispatchProgress = function (eventType) {
|
||||
var event = new XMLHttpRequest.ProgressEvent(eventType);
|
||||
event.lengthComputable = this._lengthComputable;
|
||||
event.loaded = this._loadedBytes;
|
||||
event.total = this._totalBytes;
|
||||
this.dispatchEvent(event);
|
||||
};
|
||||
XMLHttpRequest.prototype._setError = function () {
|
||||
this._request = null;
|
||||
this._response = null;
|
||||
this._responseHeaders = null;
|
||||
this._responseParts = null;
|
||||
};
|
||||
XMLHttpRequest.prototype._parseUrl = function (urlString, user, password) {
|
||||
var absoluteUrl = this.nodejsBaseUrl == null ? urlString : url.resolve(this.nodejsBaseUrl, urlString);
|
||||
var xhrUrl = url.parse(absoluteUrl, false, true);
|
||||
xhrUrl.hash = null;
|
||||
var _a = (xhrUrl.auth || '').split(':'), xhrUser = _a[0], xhrPassword = _a[1];
|
||||
if (xhrUser || xhrPassword || user || password) {
|
||||
xhrUrl.auth = (user || xhrUser || '') + ":" + (password || xhrPassword || '');
|
||||
}
|
||||
return xhrUrl;
|
||||
};
|
||||
XMLHttpRequest.prototype._parseResponseHeaders = function (response) {
|
||||
this._responseHeaders = {};
|
||||
for (var name_1 in response.headers) {
|
||||
var loweredName = name_1.toLowerCase();
|
||||
if (this._privateHeaders[loweredName]) {
|
||||
continue;
|
||||
}
|
||||
this._responseHeaders[loweredName] = response.headers[name_1];
|
||||
}
|
||||
if (this._mimeOverride != null) {
|
||||
this._responseHeaders['content-type'] = this._mimeOverride;
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.prototype._parseResponse = function () {
|
||||
var 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 (_a) {
|
||||
this.response = null;
|
||||
}
|
||||
return;
|
||||
case 'buffer':
|
||||
this.responseText = null;
|
||||
this.response = buffer;
|
||||
return;
|
||||
case 'arraybuffer':
|
||||
this.responseText = null;
|
||||
var arrayBuffer = new ArrayBuffer(buffer.length);
|
||||
var view = new Uint8Array(arrayBuffer);
|
||||
for (var 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 (_b) {
|
||||
this.responseText = buffer.toString('binary');
|
||||
}
|
||||
this.response = this.responseText;
|
||||
}
|
||||
};
|
||||
XMLHttpRequest.prototype._parseResponseEncoding = function () {
|
||||
return /;\s*charset=(.*)$/.exec(this._responseHeaders['content-type'] || '')[1] || 'utf-8';
|
||||
};
|
||||
XMLHttpRequest.ProgressEvent = progress_event_1.ProgressEvent;
|
||||
XMLHttpRequest.InvalidStateError = errors_1.InvalidStateError;
|
||||
XMLHttpRequest.NetworkError = errors_1.NetworkError;
|
||||
XMLHttpRequest.SecurityError = errors_1.SecurityError;
|
||||
XMLHttpRequest.SyntaxError = errors_1.SyntaxError;
|
||||
XMLHttpRequest.XMLHttpRequestUpload = xml_http_request_upload_1.XMLHttpRequestUpload;
|
||||
XMLHttpRequest.UNSENT = 0;
|
||||
XMLHttpRequest.OPENED = 1;
|
||||
XMLHttpRequest.HEADERS_RECEIVED = 2;
|
||||
XMLHttpRequest.LOADING = 3;
|
||||
XMLHttpRequest.DONE = 4;
|
||||
XMLHttpRequest.cookieJar = Cookie.CookieJar();
|
||||
return XMLHttpRequest;
|
||||
}(xml_http_request_event_target_1.XMLHttpRequestEventTarget));
|
||||
exports.XMLHttpRequest = XMLHttpRequest;
|
||||
XMLHttpRequest.prototype.nodejsHttpAgent = http.globalAgent;
|
||||
XMLHttpRequest.prototype.nodejsHttpsAgent = https.globalAgent;
|
||||
XMLHttpRequest.prototype.nodejsBaseUrl = null;
|
||||
//# sourceMappingURL=xml-http-request.js.map
|
1
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.js.map
vendored
1
local_modules/web3-providers-http/local_modules/xhr2-cookies/dist/xml-http-request.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@
|
||||
export class SecurityError extends Error {}
|
||||
export class InvalidStateError extends Error {}
|
||||
export class NetworkError extends Error {}
|
||||
export class SyntaxError extends Error {}
|
@ -1,2 +0,0 @@
|
||||
export * from './xml-http-request';
|
||||
export { XMLHttpRequestEventTarget } from './xml-http-request-event-target';
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"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/**/*"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
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) {}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
@ -1,101 +0,0 @@
|
||||
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
|
@ -1,249 +0,0 @@
|
||||
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');
|
||||
});
|
Binary file not shown.
Before Width: | Height: | Size: 119 B |
@ -1,189 +0,0 @@
|
||||
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
|
||||
// *
|
@ -1,50 +0,0 @@
|
||||
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-----
|
||||
`;
|
5
local_modules/web3-providers-http/local_modules/xhr2-cookies/test/helpers/certificates/generate.sh
5
local_modules/web3-providers-http/local_modules/xhr2-cookies/test/helpers/certificates/generate.sh
@ -1,5 +0,0 @@
|
||||
#!/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
|
@ -1,21 +0,0 @@
|
||||
-----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-----
|
@ -1,27 +0,0 @@
|
||||
-----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-----
|
@ -1,28 +0,0 @@
|
||||
-----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-----
|
@ -1,8 +0,0 @@
|
||||
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 };
|
@ -1,228 +0,0 @@
|
||||
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 };
|
@ -1,120 +0,0 @@
|
||||
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');
|
||||
});
|
@ -1,120 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
@ -1,134 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
@ -1,46 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
@ -1,137 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
@ -1,84 +0,0 @@
|
||||
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);
|
||||
});
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"lib": [ "es5", "es6", "es2016", "es2017", "dom" ]
|
||||
},
|
||||
"include": [
|
||||
"*.spec.ts",
|
||||
"./png.d.ts"
|
||||
]
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
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');
|
||||
});
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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']
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
@ -1,49 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,471 +0,0 @@
|
||||
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
2171
local_modules/web3-providers-http/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
/*
|
||||
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;
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
]
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
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();
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"target": "es6",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"noEmit": true,
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"web3-providers": ["."]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ethersproject/transactions": "^5.7.0",
|
||||
"@tornado/circomlib": "0.0.20-p2",
|
||||
"@tornado/fixed-merkle-tree": "0.6.1-p1",
|
||||
"@tornado/gas-price-oracle": "0.5.2-p1",
|
||||
|
Loading…
Reference in New Issue
Block a user