@ethersproject/web
Advanced tools
Comparing version 5.0.1 to 5.0.2
@@ -1,1 +0,1 @@ | ||
export declare const version = "web/5.0.1"; | ||
export declare const version = "web/5.0.2"; |
@@ -1,1 +0,2 @@ | ||
export const version = "web/5.0.1"; | ||
export const version = "web/5.0.2"; | ||
//# sourceMappingURL=_version.js.map |
@@ -47,1 +47,2 @@ "use strict"; | ||
} | ||
//# sourceMappingURL=browser-geturl.js.map |
@@ -44,2 +44,3 @@ "use strict"; | ||
resp.on("error", (error) => { | ||
/* istanbul ignore next */ | ||
error.response = response; | ||
@@ -85,2 +86,3 @@ reject(error); | ||
default: | ||
/* istanbul ignore next */ | ||
logger.throwError(`unsupported protocol ${url.protocol}`, Logger.errors.UNSUPPORTED_OPERATION, { | ||
@@ -99,1 +101,2 @@ protocol: url.protocol, | ||
} | ||
//# sourceMappingURL=geturl.js.map |
export declare type ConnectionInfo = { | ||
url: string; | ||
headers?: { | ||
[key: string]: string | number; | ||
}; | ||
user?: string; | ||
@@ -7,6 +10,5 @@ password?: string; | ||
throttleLimit?: number; | ||
throttleSlotInterval?: number; | ||
throttleCallback?: (attempt: number, url: string) => Promise<boolean>; | ||
timeout?: number; | ||
headers?: { | ||
[key: string]: string | number; | ||
}; | ||
}; | ||
@@ -13,0 +15,0 @@ export interface OnceBlockable { |
@@ -18,3 +18,14 @@ "use strict"; | ||
import { getUrl } from "./geturl"; | ||
function staller(duration) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, duration); | ||
}); | ||
} | ||
export function fetchJson(connection, json, processFunc) { | ||
// How many times to retry in the event of a throttle | ||
const attemptLimit = (typeof (connection) === "object" && connection.throttleLimit != null) ? connection.throttleLimit : 12; | ||
logger.assertArgument((attemptLimit > 0 && (attemptLimit % 1) === 0), "invalid connection throttle limit", "connection.throttleLimit", attemptLimit); | ||
const throttleCallback = ((typeof (connection) === "object") ? connection.throttleCallback : null); | ||
const throttleSlotInterval = ((typeof (connection) === "object" && typeof (connection.throttleSlotInterval) === "number") ? connection.throttleSlotInterval : 100); | ||
logger.assertArgument((throttleSlotInterval > 0 && (throttleSlotInterval % 1) === 0), "invalid connection throttle slot interval", "connection.throttleSlotInterval", throttleSlotInterval); | ||
const headers = {}; | ||
@@ -98,43 +109,48 @@ let url = null; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let response = null; | ||
try { | ||
response = yield getUrl(url, options); | ||
} | ||
catch (error) { | ||
response = error.response; | ||
if (response == null) { | ||
runningTimeout.cancel(); | ||
logger.throwError("missing response", Logger.errors.SERVER_ERROR, { | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
serverError: error, | ||
url: url | ||
}); | ||
} | ||
} | ||
let body = response.body; | ||
if (allow304 && response.statusCode === 304) { | ||
body = null; | ||
} | ||
else if (response.statusCode < 200 || response.statusCode >= 300) { | ||
runningTimeout.cancel(); | ||
logger.throwError("bad response", Logger.errors.SERVER_ERROR, { | ||
status: response.statusCode, | ||
headers: response.headers, | ||
body: body, | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
url: url | ||
}); | ||
} | ||
runningTimeout.cancel(); | ||
let json = null; | ||
if (body != null) { | ||
for (let attempt = 0; attempt < attemptLimit; attempt++) { | ||
let response = null; | ||
try { | ||
json = JSON.parse(body); | ||
response = yield getUrl(url, options); | ||
// Exponential back-off throttling | ||
if (response.statusCode === 429 && attempt < attemptLimit) { | ||
let tryAgain = true; | ||
if (throttleCallback) { | ||
tryAgain = yield throttleCallback(attempt, url); | ||
} | ||
if (tryAgain) { | ||
let stall = 0; | ||
const retryAfter = response.headers["retry-after"]; | ||
if (typeof (retryAfter) === "string" && retryAfter.match(/^[1-9][0-9]*$/)) { | ||
stall = parseInt(retryAfter) * 1000; | ||
} | ||
else { | ||
stall = throttleSlotInterval * parseInt(String(Math.random() * Math.pow(2, attempt))); | ||
} | ||
yield staller(stall); | ||
continue; | ||
} | ||
} | ||
} | ||
catch (error) { | ||
logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, { | ||
response = error.response; | ||
if (response == null) { | ||
runningTimeout.cancel(); | ||
logger.throwError("missing response", Logger.errors.SERVER_ERROR, { | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
serverError: error, | ||
url: url | ||
}); | ||
} | ||
} | ||
let body = response.body; | ||
if (allow304 && response.statusCode === 304) { | ||
body = null; | ||
} | ||
else if (response.statusCode < 200 || response.statusCode >= 300) { | ||
runningTimeout.cancel(); | ||
logger.throwError("bad response", Logger.errors.SERVER_ERROR, { | ||
status: response.statusCode, | ||
headers: response.headers, | ||
body: body, | ||
error: error, | ||
requestBody: (options.body || null), | ||
@@ -145,18 +161,48 @@ requestMethod: options.method, | ||
} | ||
} | ||
if (processFunc) { | ||
try { | ||
json = yield processFunc(json, response); | ||
let json = null; | ||
if (body != null) { | ||
try { | ||
json = JSON.parse(body); | ||
} | ||
catch (error) { | ||
runningTimeout.cancel(); | ||
logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, { | ||
body: body, | ||
error: error, | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
url: url | ||
}); | ||
} | ||
} | ||
catch (error) { | ||
logger.throwError("processing response error", Logger.errors.SERVER_ERROR, { | ||
body: json, | ||
error: error, | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
url: url | ||
}); | ||
if (processFunc) { | ||
try { | ||
json = yield processFunc(json, response); | ||
} | ||
catch (error) { | ||
// Allow the processFunc to trigger a throttle | ||
if (error.throttleRetry && attempt < attemptLimit) { | ||
let tryAgain = true; | ||
if (throttleCallback) { | ||
tryAgain = yield throttleCallback(attempt, url); | ||
} | ||
if (tryAgain) { | ||
const timeout = throttleSlotInterval * parseInt(String(Math.random() * Math.pow(2, attempt))); | ||
yield staller(timeout); | ||
continue; | ||
} | ||
} | ||
runningTimeout.cancel(); | ||
logger.throwError("processing response error", Logger.errors.SERVER_ERROR, { | ||
body: json, | ||
error: error, | ||
requestBody: (options.body || null), | ||
requestMethod: options.method, | ||
url: url | ||
}); | ||
} | ||
} | ||
runningTimeout.cancel(); | ||
return json; | ||
} | ||
return json; | ||
}); | ||
@@ -245,1 +291,2 @@ })(); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
export declare const version = "web/5.0.1"; | ||
export declare const version = "web/5.0.2"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = "web/5.0.1"; | ||
exports.version = "web/5.0.2"; | ||
//# sourceMappingURL=_version.js.map |
@@ -86,1 +86,2 @@ "use strict"; | ||
exports.getUrl = getUrl; | ||
//# sourceMappingURL=browser-geturl.js.map |
@@ -75,2 +75,3 @@ "use strict"; | ||
resp.on("error", function (error) { | ||
/* istanbul ignore next */ | ||
error.response = response; | ||
@@ -117,2 +118,3 @@ reject(error); | ||
default: | ||
/* istanbul ignore next */ | ||
logger.throwError("unsupported protocol " + url.protocol, logger_1.Logger.errors.UNSUPPORTED_OPERATION, { | ||
@@ -136,1 +138,2 @@ protocol: url.protocol, | ||
exports.getUrl = getUrl; | ||
//# sourceMappingURL=geturl.js.map |
export declare type ConnectionInfo = { | ||
url: string; | ||
headers?: { | ||
[key: string]: string | number; | ||
}; | ||
user?: string; | ||
@@ -7,6 +10,5 @@ password?: string; | ||
throttleLimit?: number; | ||
throttleSlotInterval?: number; | ||
throttleCallback?: (attempt: number, url: string) => Promise<boolean>; | ||
timeout?: number; | ||
headers?: { | ||
[key: string]: string | number; | ||
}; | ||
}; | ||
@@ -13,0 +15,0 @@ export interface OnceBlockable { |
105
lib/index.js
@@ -46,3 +46,14 @@ "use strict"; | ||
var geturl_1 = require("./geturl"); | ||
function staller(duration) { | ||
return new Promise(function (resolve) { | ||
setTimeout(resolve, duration); | ||
}); | ||
} | ||
function fetchJson(connection, json, processFunc) { | ||
// How many times to retry in the event of a throttle | ||
var attemptLimit = (typeof (connection) === "object" && connection.throttleLimit != null) ? connection.throttleLimit : 12; | ||
logger.assertArgument((attemptLimit > 0 && (attemptLimit % 1) === 0), "invalid connection throttle limit", "connection.throttleLimit", attemptLimit); | ||
var throttleCallback = ((typeof (connection) === "object") ? connection.throttleCallback : null); | ||
var throttleSlotInterval = ((typeof (connection) === "object" && typeof (connection.throttleSlotInterval) === "number") ? connection.throttleSlotInterval : 100); | ||
logger.assertArgument((throttleSlotInterval > 0 && (throttleSlotInterval % 1) === 0), "invalid connection throttle slot interval", "connection.throttleSlotInterval", throttleSlotInterval); | ||
var headers = {}; | ||
@@ -126,15 +137,40 @@ var url = null; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response, error_1, body, json, error_2; | ||
var attempt, response, tryAgain, stall, retryAfter, error_1, body, json_1, error_2, tryAgain, timeout_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
response = null; | ||
attempt = 0; | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
if (!(attempt < attemptLimit)) return [3 /*break*/, 19]; | ||
response = null; | ||
_a.label = 2; | ||
case 2: | ||
_a.trys.push([2, 8, , 9]); | ||
return [4 /*yield*/, geturl_1.getUrl(url, options)]; | ||
case 2: | ||
case 3: | ||
response = _a.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (!(response.statusCode === 429 && attempt < attemptLimit)) return [3 /*break*/, 7]; | ||
tryAgain = true; | ||
if (!throttleCallback) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, throttleCallback(attempt, url)]; | ||
case 4: | ||
tryAgain = _a.sent(); | ||
_a.label = 5; | ||
case 5: | ||
if (!tryAgain) return [3 /*break*/, 7]; | ||
stall = 0; | ||
retryAfter = response.headers["retry-after"]; | ||
if (typeof (retryAfter) === "string" && retryAfter.match(/^[1-9][0-9]*$/)) { | ||
stall = parseInt(retryAfter) * 1000; | ||
} | ||
else { | ||
stall = throttleSlotInterval * parseInt(String(Math.random() * Math.pow(2, attempt))); | ||
} | ||
return [4 /*yield*/, staller(stall)]; | ||
case 6: | ||
_a.sent(); | ||
return [3 /*break*/, 18]; | ||
case 7: return [3 /*break*/, 9]; | ||
case 8: | ||
error_1 = _a.sent(); | ||
@@ -151,4 +187,4 @@ response = error_1.response; | ||
} | ||
return [3 /*break*/, 4]; | ||
case 4: | ||
return [3 /*break*/, 9]; | ||
case 9: | ||
body = response.body; | ||
@@ -169,9 +205,9 @@ if (allow304 && response.statusCode === 304) { | ||
} | ||
runningTimeout.cancel(); | ||
json = null; | ||
json_1 = null; | ||
if (body != null) { | ||
try { | ||
json = JSON.parse(body); | ||
json_1 = JSON.parse(body); | ||
} | ||
catch (error) { | ||
runningTimeout.cancel(); | ||
logger.throwError("invalid JSON", logger_1.Logger.errors.SERVER_ERROR, { | ||
@@ -186,14 +222,30 @@ body: body, | ||
} | ||
if (!processFunc) return [3 /*break*/, 8]; | ||
_a.label = 5; | ||
case 5: | ||
_a.trys.push([5, 7, , 8]); | ||
return [4 /*yield*/, processFunc(json, response)]; | ||
case 6: | ||
json = _a.sent(); | ||
return [3 /*break*/, 8]; | ||
case 7: | ||
if (!processFunc) return [3 /*break*/, 17]; | ||
_a.label = 10; | ||
case 10: | ||
_a.trys.push([10, 12, , 17]); | ||
return [4 /*yield*/, processFunc(json_1, response)]; | ||
case 11: | ||
json_1 = _a.sent(); | ||
return [3 /*break*/, 17]; | ||
case 12: | ||
error_2 = _a.sent(); | ||
if (!(error_2.throttleRetry && attempt < attemptLimit)) return [3 /*break*/, 16]; | ||
tryAgain = true; | ||
if (!throttleCallback) return [3 /*break*/, 14]; | ||
return [4 /*yield*/, throttleCallback(attempt, url)]; | ||
case 13: | ||
tryAgain = _a.sent(); | ||
_a.label = 14; | ||
case 14: | ||
if (!tryAgain) return [3 /*break*/, 16]; | ||
timeout_1 = throttleSlotInterval * parseInt(String(Math.random() * Math.pow(2, attempt))); | ||
return [4 /*yield*/, staller(timeout_1)]; | ||
case 15: | ||
_a.sent(); | ||
return [3 /*break*/, 18]; | ||
case 16: | ||
runningTimeout.cancel(); | ||
logger.throwError("processing response error", logger_1.Logger.errors.SERVER_ERROR, { | ||
body: json, | ||
body: json_1, | ||
error: error_2, | ||
@@ -204,4 +256,10 @@ requestBody: (options.body || null), | ||
}); | ||
return [3 /*break*/, 8]; | ||
case 8: return [2 /*return*/, json]; | ||
return [3 /*break*/, 17]; | ||
case 17: | ||
runningTimeout.cancel(); | ||
return [2 /*return*/, json_1]; | ||
case 18: | ||
attempt++; | ||
return [3 /*break*/, 1]; | ||
case 19: return [2 /*return*/]; | ||
} | ||
@@ -294,1 +352,2 @@ }); | ||
exports.poll = poll; | ||
//# sourceMappingURL=index.js.map |
@@ -38,5 +38,5 @@ { | ||
}, | ||
"tarballHash": "0xf7a908584c810958cc726c4a0792aca4b422c0bfc98135f926c2c9e76ffa8fde", | ||
"tarballHash": "0x706e9cf2a72162332269c71f0e1c5ca6dbaa252e627710ed676fd342dbe89e40", | ||
"types": "./lib/index.d.ts", | ||
"version": "5.0.1" | ||
"version": "5.0.2" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
78354
28
1142