diff --git a/README.md b/README.md index a25f3bdd..8e9aaeca 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,14 @@ gaxios.request({url: '/data'}).then(...); timeout: 1000, // Optional method to override making the actual HTTP request. Useful - // for writing tests. - adapter?: (options) => { - return { - data: 'your data' - } + // for writing tests and instrumentation + adapter?: async (options, defaultAdapter) => { + const res = await defaultAdapter(options); + res.data = { + ...res.data, + extraProperty: 'your extra property', + }; + return res; }; // The expected return type of the request. Options are: diff --git a/browser-test/test.browser.ts b/browser-test/test.browser.ts index 20241e2f..cb6ddced 100644 --- a/browser-test/test.browser.ts +++ b/browser-test/test.browser.ts @@ -14,15 +14,9 @@ import assert from 'assert'; import {describe, it} from 'mocha'; import {request} from '../src/index'; -import {PassThrough} from 'stream'; -import * as stream from 'stream'; import * as uuid from 'uuid'; const port = 7172; // should match the port defined in `webserver.ts` -function isReadableStream(obj: stream.Readable | string) { - return obj instanceof stream.Readable && typeof obj._read === 'function'; -} - describe('💻 browser tests', () => { it('should just work from browser', async () => { const result = await request({url: `http://localhost:${port}/path`}); diff --git a/package.json b/package.json index ad95f5a0..35525a81 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,8 @@ "license": "Apache-2.0", "devDependencies": { "@compodoc/compodoc": "^1.1.9", + "@microsoft/api-documenter": "^7.8.10", + "@microsoft/api-extractor": "^7.8.10", "@types/cors": "^2.8.6", "@types/execa": "^0.9.0", "@types/express": "^4.16.1", @@ -55,6 +57,7 @@ "@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", @@ -83,9 +86,7 @@ "typescript": "^3.8.3", "uuid": "^8.0.0", "webpack": "^4.29.5", - "webpack-cli": "^3.2.3", - "@microsoft/api-documenter": "^7.8.10", - "@microsoft/api-extractor": "^7.8.10" + "webpack-cli": "^3.2.3" }, "dependencies": { "abort-controller": "^3.0.0", diff --git a/src/common.ts b/src/common.ts index 324974ab..258b8383 100644 --- a/src/common.ts +++ b/src/common.ts @@ -59,7 +59,10 @@ export interface GaxiosOptions { * Optional method to override making the actual HTTP request. Useful * for writing tests. */ - adapter?: (options: GaxiosOptions) => GaxiosPromise; + adapter?: ( + options: GaxiosOptions, + defaultAdapter: (options: GaxiosOptions) => GaxiosPromise + ) => GaxiosPromise; url?: string; baseUrl?: string; // deprecated baseURL?: string; diff --git a/src/gaxios.ts b/src/gaxios.ts index 44bd4f56..e22234ca 100644 --- a/src/gaxios.ts +++ b/src/gaxios.ts @@ -90,6 +90,14 @@ export class Gaxios { return this._request(opts); } + private async _defaultAdapter( + opts: GaxiosOptions + ): Promise> { + const res = await fetch(opts.url!, opts); + const data = await this.getResponseData(opts, res); + return this.translateResponse(opts, res, data); + } + /** * Internal, retryable version of the `request` method. * @param opts Set of HTTP options that will be used for this HTTP request. @@ -98,11 +106,12 @@ export class Gaxios { try { let translatedResponse: GaxiosResponse; if (opts.adapter) { - translatedResponse = await opts.adapter(opts); + translatedResponse = await opts.adapter( + opts, + this._defaultAdapter.bind(this) + ); } else { - const res = await fetch(opts.url!, opts); - const data = await this.getResponseData(opts, res); - translatedResponse = this.translateResponse(opts, res, data); + translatedResponse = await this._defaultAdapter(opts); } if (!opts.validateStatus!(translatedResponse.status)) { throw new GaxiosError( diff --git a/system-test/fixtures/sample/webpack.config.js b/system-test/fixtures/sample/webpack.config.js index b3ced2ce..7425acb0 100644 --- a/system-test/fixtures/sample/webpack.config.js +++ b/system-test/fixtures/sample/webpack.config.js @@ -32,6 +32,8 @@ module.exports = { child_process: 'empty', fs: 'empty', crypto: 'empty', + net: 'empty', + tls: 'empty', }, module: { rules: [ diff --git a/test/test.getch.ts b/test/test.getch.ts index 98b336db..056c39ac 100644 --- a/test/test.getch.ts +++ b/test/test.getch.ts @@ -131,6 +131,34 @@ describe('🥁 configuration options', () => { assert.strictEqual(response, res); }); + it('should allow overriding the adapter with default adapter wrapper', async () => { + const body = {hello: '🌎'}; + const extraProperty = '🦦'; + const scope = nock(url).get('/').reply(200, body); + const timings: {duration: number}[] = []; + const res = await request({ + url, + adapter: async (opts, defaultAdapter) => { + const begin = Date.now(); + const res = await defaultAdapter(opts); + const end = Date.now(); + res.data = { + ...res.data, + extraProperty, + }; + timings.push({duration: end - begin}); + return res; + }, + }); + scope.done(); + assert.deepStrictEqual(res.data, { + ...body, + extraProperty, + }); + assert(timings.length === 1); + assert(typeof timings[0].duration === 'number'); + }); + it('should encode URL parameters', async () => { const path = '/?james=kirk&montgomery=scott'; const opts = {url: `${url}${path}`}; diff --git a/webpack-tests.config.js b/webpack-tests.config.js index d903551d..3c0b3072 100644 --- a/webpack-tests.config.js +++ b/webpack-tests.config.js @@ -27,6 +27,8 @@ module.exports = { child_process: 'empty', fs: 'empty', crypto: 'empty', + net: 'empty', + tls: 'empty', }, module: { rules: [ diff --git a/webpack.config.js b/webpack.config.js index 012df506..b56c6f1b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -33,6 +33,8 @@ module.exports = { child_process: 'empty', fs: 'empty', crypto: 'empty', + net: 'empty', + tls: 'empty', }, module: { rules: [