From 2d5564a56d0d8ccb6883c2b3ef34b659aa3affe5 Mon Sep 17 00:00:00 2001 From: James Brotchie Date: Fri, 11 Feb 2022 15:11:06 -0800 Subject: [PATCH] Add sendCredentials option to createFetchMiddleware to include all cookies for cross-origin calls. createFetchMiddleware doesn't support calling into am Eth JSON RPC Node that's protected by cookie-based authentication. The standard approach to solving this is to tell fetch to send cookies along with CORS requests. This change adds a sendCredentials option to createFetchMiddleware that, when set to true, indicates cookies to be send for CORS requests. --- src/fetch.ts | 9 +++++++++ test/fetch.js | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/fetch.ts b/src/fetch.ts index 05ff49dc..f60525a4 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -25,6 +25,7 @@ interface Request { method: string; headers: Record; body: string; + credentials?: 'include' | 'omit' | 'same-origin'; } interface FetchConfig { fetchUrl: string; @@ -33,6 +34,7 @@ interface FetchConfig { interface FetchMiddlewareOptions { rpcUrl: string; originHttpHeaderKey?: string; + sendCredentials?: boolean; } interface FetchMiddlewareFromReqOptions extends FetchMiddlewareOptions { @@ -42,12 +44,14 @@ interface FetchMiddlewareFromReqOptions extends FetchMiddlewareOptions { export function createFetchMiddleware({ rpcUrl, originHttpHeaderKey, + sendCredentials, }: FetchMiddlewareOptions): JsonRpcMiddleware { return createAsyncMiddleware(async (req, res, _next) => { const { fetchUrl, fetchParams } = createFetchConfigFromReq({ req, rpcUrl, originHttpHeaderKey, + sendCredentials, }); // attempt request multiple times @@ -129,6 +133,7 @@ export function createFetchConfigFromReq({ req, rpcUrl, originHttpHeaderKey, + sendCredentials, }: FetchMiddlewareFromReqOptions): FetchConfig { const parsedUrl: URL = new URL(rpcUrl); const fetchUrl: string = normalizeUrlFromParsed(parsedUrl); @@ -170,6 +175,10 @@ export function createFetchConfigFromReq({ fetchParams.headers[originHttpHeaderKey] = originDomain; } + if (sendCredentials === true) { + fetchParams.credentials = 'include'; + } + return { fetchUrl, fetchParams }; } diff --git a/test/fetch.js b/test/fetch.js index 9e76837a..c69d1f2d 100644 --- a/test/fetch.js +++ b/test/fetch.js @@ -56,6 +56,31 @@ test('fetch - origin header', (t) => { t.end(); }); +test('fetch - send credentials', (t) => { + const req = { + method: 'eth_getBlockByNumber', + params: ['0x482103', true], + }; + const rpcUrl = 'http://www.xyz.io/rabbit:3456?id=100'; + const { fetchUrl, fetchParams } = createFetchConfigFromReq({ + req, + rpcUrl, + sendCredentials: true, + }); + + t.equals(fetchUrl, rpcUrl); + t.deepEquals(fetchParams, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(req), + credentials: 'include', + }); + t.end(); +}); + test('fetch - auth in url', (t) => { const req = { method: 'eth_getBlockByNumber',