From 3d25882d6bf689740506b9c569f6e0d30da6f6a5 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Fri, 27 Sep 2019 21:55:40 -0400 Subject: [PATCH] Add response handling and 304 support to fetchJson. --- packages/ethers/src.ts/utils.ts | 3 +- packages/web/src.ts/index.ts | 81 ++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/packages/ethers/src.ts/utils.ts b/packages/ethers/src.ts/utils.ts index 060eaa2eb1..826633c2d2 100644 --- a/packages/ethers/src.ts/utils.ts +++ b/packages/ethers/src.ts/utils.ts @@ -33,7 +33,7 @@ import { UnicodeNormalizationForm } from "@ethersproject/strings"; import { CoerceFunc } from "@ethersproject/abi"; import { Bytes, BytesLike, Hexable } from "@ethersproject/bytes" -import { ConnectionInfo, OnceBlockable, PollOptions } from "@ethersproject/web"; +import { ConnectionInfo, FetchJsonResponse, OnceBlockable, PollOptions } from "@ethersproject/web"; import { EncryptOptions, ProgressCallback } from "@ethersproject/json-wallets"; //////////////////////// @@ -164,6 +164,7 @@ export { ConnectionInfo, OnceBlockable, PollOptions, + FetchJsonResponse, EncryptOptions, ProgressCallback diff --git a/packages/web/src.ts/index.ts b/packages/web/src.ts/index.ts index ca5e4c259a..b5d4a32a00 100644 --- a/packages/web/src.ts/index.ts +++ b/packages/web/src.ts/index.ts @@ -33,11 +33,16 @@ export type PollOptions = { onceBlock?: OnceBlockable }; +export type FetchJsonResponse = { + statusCode: number; + status: string; + headers: { [ header: string ]: string }; +}; type Header = { key: string, value: string }; -export function fetchJson(connection: string | ConnectionInfo, json?: string, processFunc?: (value: any) => any): Promise { +export function fetchJson(connection: string | ConnectionInfo, json?: string, processFunc?: (value: any, response: FetchJsonResponse) => any): Promise { let headers: { [key: string]: Header } = { }; let url: string = null; @@ -52,6 +57,8 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr referrer: "client", // no-referrer, *client }; + let allow304 = false; + let timeout = 2 * 60 * 1000; if (typeof(connection) === "string") { @@ -71,6 +78,9 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr if (connection.headers) { for (let key in connection.headers) { headers[key.toLowerCase()] = { key: key, value: String(connection.headers[key]) }; + if (["if-none-match", "if-modified-since"].indexOf(key.toLowerCase()) >= 0) { + allow304 = true; + } } } @@ -124,42 +134,59 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr return fetch(url, options).then((response) => { return response.text().then((body) => { - if (!response.ok) { + + let json: any = null; + + if (allow304 && response.status === 304) { + // Leave json as null + + } else if (!response.ok) { logger.throwError("bad response", Logger.errors.SERVER_ERROR, { status: response.status, body: body, type: response.type, url: response.url }); - } - return body; - }); - - }).then((text) => { - let json: any = null; - try { - json = JSON.parse(text); - } catch (error) { - logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, { - body: text, - error: error, - url: url - }); - } + } else { + try { + json = JSON.parse(body); + } catch (error) { + logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, { + body: body, + error: error, + url: url + }); + } + } - if (processFunc) { - try { - json = processFunc(json); - } catch (error) { - logger.throwError("processing response error", Logger.errors.SERVER_ERROR, { - body: json, - error: error - }); + if (processFunc) { + try { + const headers: { [ header: string ]: string } = { }; + if (response.headers.forEach) { + response.headers.forEach((value, key) => { + headers[key.toLowerCase()] = value; + }); + } else { + (<() => Array>(((response.headers)).keys))().forEach((key) => { + headers[key.toLowerCase()] = response.headers.get(key); + }); + } + json = processFunc(json, { + statusCode: response.status, + status: response.statusText, + headers: headers + }); + } catch (error) { + logger.throwError("processing response error", Logger.errors.SERVER_ERROR, { + body: json, + error: error + }); + } } - } - return json; + return json; + }); }, (error) => { throw error;