Skip to content

Commit

Permalink
feat: add an option to configure the fetch impl (#342)
Browse files Browse the repository at this point in the history
  • Loading branch information
JustinBeckwith authored Nov 17, 2020
1 parent 9048be4 commit 2e081ef
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 16 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ gaxios.request({url: '/data'}).then(...);
// status code. Defaults to (>= 200 && < 300)
validateStatus: (status: number) => true,

// Implementation of `fetch` to use when making the API call. By default,
// will use the browser context if available, and fall back to `node-fetch`
// in node.js otherwise.
fetchImplementation?: typeof fetch;

// Configuration for retrying of requests.
retryConfig: {
// The number of times to retry the request. Defaults to 3.
Expand Down
5 changes: 5 additions & 0 deletions browser-test/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"env": {
"browser": true
}
}
8 changes: 8 additions & 0 deletions browser-test/test.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ describe('💻 browser tests', () => {
assert.strictEqual(result.data, 'value');
});

it('should allow passing browser fetch explicitly', async () => {
const result = await request({
url: `http://localhost:${port}/path`,
fetchImplementation: window.fetch,
});
assert.strictEqual(result.status, 200);
});

it('should support multipart post from the browser', async () => {
const headers: {[key: string]: string} = {};
const multipart = [
Expand Down
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint": "gts check",
"test": "c8 mocha build/test",
"presystem-test": "npm run compile",
"system-test": "mocha build/system-test --timeout 40000",
"system-test": "mocha build/system-test --timeout 80000",
"compile": "tsc -p .",
"fix": "gts fix",
"prepare": "npm run compile",
Expand Down Expand Up @@ -50,15 +50,12 @@
"@types/multiparty": "0.0.32",
"@types/mv": "^2.1.0",
"@types/ncp": "^2.0.1",
"@types/nock": "^10.0.0",
"@types/node": "^11.9.5",
"@types/node-fetch": "^2.1.6",
"@types/node-fetch": "^2.5.7",
"@types/sinon": "^9.0.0",
"@types/tmp": "0.2.0",
"@types/uuid": "^8.0.0",
"c8": "^7.0.0",
"chai": "^4.2.0",
"codecov": "^3.2.0",
"cors": "^2.8.5",
"execa": "^4.0.0",
"express": "^4.16.4",
Expand Down
7 changes: 3 additions & 4 deletions samples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
"test": "mocha"
},
"license": "Apache-2.0",
"devDependencies": {
"chai": "^4.2.0",
"mocha": "^8.0.0"
},
"dependencies": {
"gaxios": "^4.0.1"
},
"devDependencies": {
"mocha": "^8.0.0"
}
}
4 changes: 2 additions & 2 deletions samples/test/test.samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
// limitations under the License.

const {execSync} = require('child_process');
const {assert} = require('chai');
const assert = require('assert');
const {describe, it} = require('mocha');

const exec = cmd => execSync(cmd, {encoding: 'utf8'});

describe(__filename, () => {
it('should run the quickstart', () => {
const output = exec('node quickstart');
assert.include(output, 'status: 200');
assert.ok(output.includes('status: 200'));
});
});
41 changes: 41 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ export interface GaxiosOptions {
retry?: boolean;
signal?: AbortSignal;
size?: number;
/**
* Implementation of `fetch` to use when making the API call. By default,
* will use the browser context if available, and fall back to `node-fetch`
* in node.js otherwise.
*/
fetchImplementation?: FetchImplementation;
}

/**
Expand Down Expand Up @@ -147,3 +153,38 @@ export interface RetryConfig {
*/
noResponseRetries?: number;
}

export type FetchImplementation = (
input: FetchRequestInfo,
init?: FetchRequestInit
) => Promise<FetchResponse>;

export type FetchRequestInfo = any;

export interface FetchResponse {
readonly status: number;
readonly statusText: string;
readonly url: string;
readonly body: unknown | null;
arrayBuffer(): Promise<unknown>;
blob(): Promise<unknown>;
readonly headers: FetchHeaders;
json(): Promise<any>;
text(): Promise<string>;
}

export interface FetchRequestInit {
method?: string;
}

export interface FetchHeaders {
append(name: string, value: string): void;
delete(name: string): void;
get(name: string): string | null;
has(name: string): boolean;
set(name: string, value: string): void;
forEach(
callbackfn: (value: string, key: string) => void,
thisArg?: any
): void;
}
11 changes: 6 additions & 5 deletions src/gaxios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@

import extend from 'extend';
import {Agent} from 'http';
import nodeFetch, {Response as NodeFetchResponse} from 'node-fetch';
import nodeFetch from 'node-fetch';
import qs from 'querystring';
import isStream from 'is-stream';
import url from 'url';

import {
FetchResponse,
GaxiosError,
GaxiosOptions,
GaxiosPromise,
Expand All @@ -28,7 +29,6 @@ import {
import {getRetryConfig} from './retry';

/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable node/no-unsupported-features/node-builtins */

const fetch = hasFetch() ? window.fetch : nodeFetch;

Expand Down Expand Up @@ -88,7 +88,8 @@ export class Gaxios {
private async _defaultAdapter<T>(
opts: GaxiosOptions
): Promise<GaxiosResponse<T>> {
const res = await fetch(opts.url!, opts);
const fetchImpl = opts.fetchImplementation || fetch;
const res = (await fetchImpl(opts.url!, opts)) as FetchResponse;
const data = await this.getResponseData(opts, res);
return this.translateResponse<T>(opts, res, data);
}
Expand Down Expand Up @@ -130,7 +131,7 @@ export class Gaxios {

private async getResponseData(
opts: GaxiosOptions,
res: Response | NodeFetchResponse
res: FetchResponse
): Promise<any> {
switch (opts.responseType) {
case 'stream':
Expand Down Expand Up @@ -250,7 +251,7 @@ export class Gaxios {

private translateResponse<T>(
opts: GaxiosOptions,
res: Response | NodeFetchResponse,
res: FetchResponse,
data?: T
): GaxiosResponse<T> {
// headers need to be converted from a map to an obj
Expand Down
8 changes: 8 additions & 0 deletions test/test.getch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import nock from 'nock';
import sinon from 'sinon';
import stream from 'stream';
import {describe, it, afterEach} from 'mocha';
import fetch from 'node-fetch';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const HttpsProxyAgent = require('https-proxy-agent');
import {
Expand Down Expand Up @@ -277,6 +278,13 @@ describe('🥁 configuration options', () => {
scope.done();
assert.deepStrictEqual(res.config.data, body);
});

it('should allow explicitly setting the fetch implementation to node-fetch', async () => {
const scope = nock(url).get('/').reply(200);
const res = await request({url, fetchImplementation: fetch});
scope.done();
assert.deepStrictEqual(res.status, 200);
});
});

describe('🎏 data handling', () => {
Expand Down

0 comments on commit 2e081ef

Please sign in to comment.