Skip to content
This repository was archived by the owner on Nov 20, 2025. It is now read-only.

Commit b6852df

Browse files
committed
refactor: Use Gaxios Interceptors for default Auth headers
1 parent 8bdeec9 commit b6852df

File tree

2 files changed

+74
-31
lines changed

2 files changed

+74
-31
lines changed

src/auth/authclient.ts

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ export interface AuthClientOptions
8383

8484
/**
8585
* The {@link Gaxios `Gaxios`} instance used for making requests.
86+
*
87+
* @see {@link AuthClientOptions.useAuthRequestParameters}
8688
*/
8789
gaxios?: Gaxios;
8890

@@ -106,6 +108,19 @@ export interface AuthClientOptions
106108
* on the expiry_date.
107109
*/
108110
forceRefreshOnFailure?: boolean;
111+
112+
/**
113+
* Enables/disables the adding of the AuthClient's default interceptor.
114+
*
115+
* @see {@link AuthClientOptions.gaxios}
116+
*
117+
* @remarks
118+
*
119+
* Disabling is useful for debugging and experimentation.
120+
*
121+
* @default true
122+
*/
123+
useAuthRequestParameters?: boolean;
109124
}
110125

111126
/**
@@ -210,6 +225,12 @@ export abstract class AuthClient
210225
// Shared client options
211226
this.transporter = opts.gaxios ?? new Gaxios(opts.transporterOptions);
212227

228+
if (options.get('useAuthRequestParameters') !== false) {
229+
this.transporter.interceptors.request.add(
230+
AuthClient.DEFAULT_REQUEST_INTERCEPTOR
231+
);
232+
}
233+
213234
if (opts.eagerRefreshThresholdMillis) {
214235
this.eagerRefreshThresholdMillis = opts.eagerRefreshThresholdMillis;
215236
}
@@ -224,37 +245,6 @@ export abstract class AuthClient
224245
*/
225246
abstract request<T>(options: GaxiosOptions): GaxiosPromise<T>;
226247

227-
/**
228-
* The internal request handler.
229-
*
230-
* @privateRemarks
231-
*
232-
* At this stage the credentials have been already prepared - passing it
233-
* here adds the standard headers to the request, if not previously configured.
234-
*
235-
* @param options options for `gaxios`
236-
*/
237-
protected _request<T>(options: GaxiosOptions): GaxiosPromise<T> {
238-
const headers = options.headers || {};
239-
240-
// Set `x-goog-api-client`, if not already set
241-
if (!headers['x-goog-api-client']) {
242-
const nodeVersion = process.version.replace(/^v/, '');
243-
headers['x-goog-api-client'] = `gl-node/${nodeVersion}`;
244-
}
245-
246-
// Set `User-Agent`
247-
if (!headers['User-Agent']) {
248-
headers['User-Agent'] = USER_AGENT;
249-
} else if (!headers['User-Agent'].includes(`${PRODUCT_NAME}/`)) {
250-
headers['User-Agent'] = `${headers['User-Agent']} ${USER_AGENT}`;
251-
}
252-
253-
options.headers = headers;
254-
255-
return this.transporter.request<T>(options);
256-
}
257-
258248
/**
259249
* The main authentication interface. It takes an optional url which when
260250
* present is the endpoint being accessed, and returns a Promise which
@@ -303,6 +293,31 @@ export abstract class AuthClient
303293
return headers;
304294
}
305295

296+
static readonly DEFAULT_REQUEST_INTERCEPTOR: Parameters<
297+
Gaxios['interceptors']['request']['add']
298+
>[0] = {
299+
resolved: async config => {
300+
const headers = config.headers || {};
301+
302+
// Set `x-goog-api-client`, if not already set
303+
if (!headers['x-goog-api-client']) {
304+
const nodeVersion = process.version.replace(/^v/, '');
305+
headers['x-goog-api-client'] = `gl-node/${nodeVersion}`;
306+
}
307+
308+
// Set `User-Agent`
309+
if (!headers['User-Agent']) {
310+
headers['User-Agent'] = USER_AGENT;
311+
} else if (!headers['User-Agent'].includes(`${PRODUCT_NAME}/`)) {
312+
headers['User-Agent'] = `${headers['User-Agent']} ${USER_AGENT}`;
313+
}
314+
315+
config.headers = headers;
316+
317+
return config;
318+
},
319+
};
320+
306321
/**
307322
* Retry config for Auth-related requests.
308323
*

test/test.authclient.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {strict as assert} from 'assert';
1616

1717
import {PassThroughClient} from '../src';
1818
import {snakeToCamel} from '../src/util';
19+
import {Gaxios} from 'gaxios';
1920

2021
describe('AuthClient', () => {
2122
it('should accept and normalize snake case options to camel case', () => {
@@ -38,4 +39,31 @@ describe('AuthClient', () => {
3839
assert.equal(authClient[camelCased], value);
3940
}
4041
});
42+
43+
it('should allow disabling of the default interceptor', () => {
44+
const gaxios = new Gaxios();
45+
const originalInterceptorCount = gaxios.interceptors.request.size;
46+
47+
const authClient = new PassThroughClient({
48+
gaxios,
49+
useAuthRequestParameters: false,
50+
});
51+
52+
assert.equal(authClient.transporter, gaxios);
53+
assert.equal(
54+
authClient.transporter.interceptors.request.size,
55+
originalInterceptorCount
56+
);
57+
});
58+
59+
it('should add the default interceptor exactly once between instances', () => {
60+
const gaxios = new Gaxios();
61+
const originalInterceptorCount = gaxios.interceptors.request.size;
62+
const expectedInterceptorCount = originalInterceptorCount + 1;
63+
64+
new PassThroughClient({gaxios});
65+
new PassThroughClient({gaxios});
66+
67+
assert.equal(gaxios.interceptors.request.size, expectedInterceptorCount);
68+
});
4169
});

0 commit comments

Comments
 (0)