Skip to content

Commit 43a8cb8

Browse files
authored
feat!: Update google-auth-library to v10 (#1702)
* feat!: Update `google-auth-library` to v10 * style: lint * chore: streamline auth with rc.1 * fix: typo * chore: bump rc * chore: webpack * test: fix * refactor: extend `FetchParameters#headers` compat * test: fix webpack config and tests
1 parent 5ef89de commit 43a8cb8

15 files changed

+332
-329
lines changed

gax/package.json

+1-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"@types/long": "^5.0.0",
1616
"abort-controller": "^3.0.0",
1717
"duplexify": "^4.1.3",
18-
"google-auth-library": "^9.15.1",
18+
"google-auth-library": "^10.0.0-rc.1",
1919
"node-fetch": "^3.3.2",
2020
"object-hash": "^3.0.0",
2121
"proto3-json-serializer": "^3.0.0",
@@ -27,15 +27,12 @@
2727
"@types/mocha": "^10.0.10",
2828
"@types/ncp": "^2.0.8",
2929
"@types/node": "^20.5.0",
30-
"@types/node-fetch": "^2.6.12",
3130
"@types/object-hash": "^3.0.6",
3231
"@types/proxyquire": "^1.3.31",
3332
"@types/pumpify": "^1.4.4",
3433
"@types/sinon": "^17.0.3",
3534
"@types/uglify-js": "^3.17.5",
36-
"assert": "^2.1.0",
3735
"c8": "^10.1.3",
38-
"cheerio": "^1.0.0",
3936
"codecov": "^3.8.3",
4037
"execa": "^5.0.0",
4138
"glob": "10.4.5",

gax/src/fallback.ts

+32-35
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,7 @@ import * as protobuf from 'protobufjs';
2020
import * as gax from './gax';
2121
import * as routingHeader from './routingHeader';
2222
import {Status} from './status';
23-
import {
24-
GoogleAuth,
25-
OAuth2Client,
26-
Compute,
27-
JWT,
28-
UserRefreshClient,
29-
GoogleAuthOptions,
30-
BaseExternalAccountClient,
31-
} from 'google-auth-library';
23+
import {GoogleAuth, AuthClient} from 'google-auth-library';
3224
import {OperationsClientBuilder} from './operationsClient';
3325
import type {GrpcClientOptions, ClientStubOptions} from './grpc';
3426
import {GaxCall, GRPCCall} from './apitypes';
@@ -85,15 +77,16 @@ export interface ServiceMethods {
8577
[name: string]: protobuf.Method;
8678
}
8779

88-
export type AuthClient =
89-
| OAuth2Client
90-
| Compute
91-
| JWT
92-
| UserRefreshClient
93-
| BaseExternalAccountClient;
80+
/**
81+
* @deprecated use `GoogleAuth` here instead
82+
*/
83+
type deprecatedAuthClientAlias = AuthClient;
9484

9585
export class GrpcClient {
96-
auth?: OAuth2Client | GoogleAuth;
86+
auth?: GoogleAuth<AuthClient> | deprecatedAuthClientAlias;
87+
/**
88+
* @deprecated use {@link GrpcClient.auth} instead
89+
*/
9790
authClient?: AuthClient;
9891
fallback: boolean;
9992
grpcVersion: string;
@@ -114,33 +107,36 @@ export class GrpcClient {
114107
* gRPC-fallback version of GrpcClient
115108
* Implements GrpcClient API for a browser using grpc-fallback protocol (sends serialized protobuf to HTTP/1 $rpc endpoint).
116109
*
117-
* @param {Object=} options.auth - An instance of OAuth2Client to use in browser, or an instance of GoogleAuth from google-auth-library
118-
* to use in Node.js. Required for browser, optional for Node.js.
119-
* @constructor
110+
* @param options {@link GrpcClientOptions}
120111
*/
121-
122112
constructor(
123-
options: (GrpcClientOptions | {auth: OAuth2Client}) & {
113+
options: (
114+
| GrpcClientOptions
115+
| {
116+
/**
117+
* @deprecated - use `authClient` for `AuthClient`s instead
118+
*/
119+
auth: AuthClient;
120+
}
121+
) & {
124122
/**
125123
* Fallback mode to use instead of gRPC.
126124
* A string is accepted for compatibility, all non-empty string values enable the HTTP REST fallback.
127125
*/
128126
fallback?: boolean | string;
129127
} = {},
130128
) {
131-
if (!isNodeJS()) {
132-
if (!options.auth) {
133-
throw new Error(
134-
JSON.stringify(options) +
135-
'You need to pass auth instance to use gRPC-fallback client in browser or other non-Node.js environments. Use OAuth2Client from google-auth-library.',
136-
);
137-
}
138-
this.auth = options.auth as OAuth2Client;
129+
if (options.auth) {
130+
this.auth = options.auth;
131+
} else if ('authClient' in options) {
132+
this.auth = options.authClient;
139133
} else {
140-
this.auth =
141-
(options.auth as GoogleAuth) ||
142-
new GoogleAuth(options as GoogleAuthOptions);
134+
this.auth = new GoogleAuth({
135+
authClient: options.auth,
136+
...options,
137+
});
143138
}
139+
144140
this.fallback = options.fallback ? true : false;
145141
this.grpcVersion = require('../../package.json').version;
146142
this.httpRules = (options as GrpcClientOptions).httpRules;
@@ -266,7 +262,7 @@ export class GrpcClient {
266262

267263
/**
268264
* gRPC-fallback version of createStub
269-
* Creates a gRPC-fallback stub with authentication headers built from supplied OAuth2Client instance
265+
* Creates a gRPC-fallback stub with authentication headers built from supplied `AuthClient` instance
270266
*
271267
* @param {function} CreateStub - The constructor function of the stub.
272268
* @param {Object} service - A protobufjs Service object (as returned by lookupService)
@@ -284,7 +280,7 @@ export class GrpcClient {
284280
) {
285281
if (!this.authClient) {
286282
if (this.auth && 'getClient' in this.auth) {
287-
this.authClient = (await this.auth.getClient()) as AuthClient;
283+
this.authClient = await this.auth.getClient();
288284
} else if (this.auth && 'getRequestHeaders' in this.auth) {
289285
this.authClient = this.auth;
290286
}
@@ -342,7 +338,7 @@ export class GrpcClient {
342338
protocol,
343339
servicePath,
344340
servicePort,
345-
this.authClient,
341+
this.auth || this.authClient,
346342
encoder,
347343
decoder,
348344
this.numericEnums,
@@ -425,6 +421,7 @@ export function createApiCall(
425421
};
426422
}
427423
if (descriptor && 'streaming' in descriptor && !isNodeJS()) {
424+
// TODO: with `fetch` this functionality is available in the browser...
428425
return () => {
429426
throw new Error(
430427
'Server streaming over the REST transport is only supported in Node.js.',

gax/src/fallbackServiceStub.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ import type {
2222
RequestInit,
2323
} from 'node-fetch' with {'resolution-mode': 'import'};
2424
import {AbortController as NodeAbortController} from 'abort-controller';
25+
26+
import {AuthClient, GoogleAuth, gaxios} from 'google-auth-library';
27+
2528
import type nodeFetch from 'node-fetch' with {'resolution-mode': 'import'};
2629
import {hasWindowFetch, hasAbortController, isNodeJS} from './featureDetection';
27-
import {AuthClient} from './fallback';
2830
import {StreamArrayParser} from './streamArrayParser';
2931
import {pipeline, PipelineSource} from 'stream';
3032
import type {Agent as HttpAgent} from 'http';
@@ -38,7 +40,9 @@ interface NodeFetchType {
3840
// Node.js before v19 does not enable keepalive by default.
3941
// We'll try to enable it very carefully to make sure we don't break possible non-Node use cases.
4042
// TODO: remove this after Node 18 is EOL.
41-
// More info: https://github.com/node-fetch/node-fetch#custom-agent
43+
// More info:
44+
// - https://github.com/node-fetch/node-fetch#custom-agent
45+
// - https://github.com/googleapis/gax-nodejs/pull/1534
4246
let agentOption:
4347
| ((parsedUrl: {protocol: string}) => HttpAgent | HttpsAgent)
4448
| null = null;
@@ -68,7 +72,7 @@ export interface FallbackServiceStub {
6872
export type FetchParametersMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
6973

7074
export interface FetchParameters {
71-
headers: {[key: string]: string};
75+
headers: {[key: string]: string} | Headers;
7276
body: Buffer | Uint8Array | string;
7377
method: FetchParametersMethod;
7478
url: string;
@@ -79,7 +83,7 @@ export function generateServiceStub(
7983
protocol: string,
8084
servicePath: string,
8185
servicePort: number,
82-
authClient: AuthClient,
86+
auth: GoogleAuth | AuthClient,
8387
requestEncoder: (
8488
rpc: protobuf.Method,
8589
protocol: string,
@@ -147,20 +151,17 @@ export function generateServiceStub(
147151
const cancelSignal = cancelController.signal as AbortSignal;
148152
let cancelRequested = false;
149153
const url = fetchParameters.url;
150-
const headers = fetchParameters.headers;
154+
const headers = new Headers(fetchParameters.headers);
151155
for (const key of Object.keys(options)) {
152-
headers[key] = options[key][0];
156+
headers.set(key, options[key][0]);
153157
}
154158
const streamArrayParser = new StreamArrayParser(rpc);
155159

156-
authClient
160+
auth
157161
.getRequestHeaders()
158162
.then(authHeader => {
159163
const fetchRequest: RequestInit = {
160-
headers: {
161-
...authHeader,
162-
...headers,
163-
},
164+
headers: gaxios.Gaxios.mergeHeaders(authHeader, headers) as {},
164165
body: fetchParameters.body as string | Buffer | undefined,
165166
method: fetchParameters.method,
166167
signal: cancelSignal,

gax/src/grpc.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,17 @@ export class GrpcClient {
210210
const client = await this.auth.getClient();
211211
const credentials = grpc.credentials.combineChannelCredentials(
212212
sslCreds,
213-
grpc.credentials.createFromGoogleCredential(client),
213+
grpc.credentials.createFromGoogleCredential({
214+
// the `grpc` package does not support the `Headers` object yet
215+
getRequestHeaders: async (url?: string | URL) => {
216+
const headers = await client.getRequestHeaders(url);
217+
const genericHeadersObject: Record<string, string> = {};
218+
219+
headers.forEach((value, key) => (genericHeadersObject[key] = value));
220+
221+
return genericHeadersObject;
222+
},
223+
}),
214224
);
215225
return credentials;
216226
}

gax/src/iamService.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import * as gax from './gax';
2020
import type {GrpcClient, ClientStubOptions} from './grpc';
2121
import type {GrpcClient as FallbackGrpcClient} from './fallback';
2222
import {createApiCall} from './createApiCall';
23-
import {GoogleAuth, OAuth2Client} from 'google-auth-library';
23+
import {GoogleAuth, AuthClient} from 'google-auth-library';
2424
import {ProjectIdCallback} from 'google-auth-library/build/src/auth/googleauth';
2525
import * as routingHeader from './routingHeader';
2626
import * as gapicConfig from './iam_policy_service_client_config.json';
@@ -40,7 +40,7 @@ export class IamClient {
4040
private _defaults: {[method: string]: gax.CallSettings};
4141
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4242
private _protos: any;
43-
auth?: GoogleAuth | OAuth2Client;
43+
auth?: GoogleAuth | AuthClient;
4444
descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}};
4545
innerApiCalls: {[name: string]: Function} = {};
4646
iamPolicyStub?: Promise<{[name: string]: Function}>;

gax/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import * as operationsClient from './operationsClient';
2323
import * as routingHeader from './routingHeader';
2424

2525
export {GoogleAuth, GoogleAuthOptions} from 'google-auth-library';
26+
export * as googleAuthLibrary from 'google-auth-library';
27+
2628
export {grpc};
2729
export {CancellablePromise, OngoingCall} from './call';
2830
export {createApiCall} from './createApiCall';

gax/src/operationsClient.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import type {GoogleAuth, OAuth2Client} from 'google-auth-library';
17+
import type {GoogleAuth, AuthClient} from 'google-auth-library';
1818
import {ProjectIdCallback} from 'google-auth-library/build/src/auth/googleauth';
1919
import type {ClientOptions, Callback} from './clientInterface';
2020

@@ -62,7 +62,7 @@ export const ALL_SCOPES: string[] = [];
6262
* @class
6363
*/
6464
export class OperationsClient {
65-
auth?: GoogleAuth | OAuth2Client;
65+
auth?: GoogleAuth | AuthClient;
6666
innerApiCalls: {[name: string]: Function};
6767
descriptor: {[method: string]: PageDescriptor};
6868
operationsStub: Promise<{[method: string]: Function}>;

gax/test/browser-test/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
"@types/node": "^20.5.0",
2929
"@types/sinon": "^10.0.13",
3030
"assert": "^2.1.0",
31+
"browserify-zlib": "^0.2.0",
3132
"core-js": "^3.40.0",
33+
"crypto-browserify": "^3.12.1",
3234
"google-gax": "./google-gax.tgz",
3335
"https-browserify": "^1.0.0",
3436
"is-docker": "^2.2.1",
@@ -39,6 +41,8 @@
3941
"karma-sourcemap-loader": "^0.4.0",
4042
"karma-webpack": "^5.0.1",
4143
"mocha": "^10.0.0",
44+
"os-browserify": "^0.3.0",
45+
"path-browserify": "^1.0.1",
4246
"process": "^0.11.10",
4347
"puppeteer": "^16.0.0",
4448
"querystring-es3": "^0.2.1",

gax/test/browser-test/test/test.endtoend.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@ function sleep(timeout: number) {
2828

2929
describe('Run tests against gRPC server', async function () {
3030
const authStub = {
31+
getRequestHeaders: async () => {
32+
return new Headers({
33+
Authorization: 'Bearer zzzz',
34+
});
35+
},
3136
getClient: async () => {
3237
return {
3338
getRequestHeaders: async () => {
34-
return {
39+
return new Headers({
3540
Authorization: 'Bearer zzzz',
36-
};
41+
});
3742
},
3843
};
3944
},
@@ -71,7 +76,7 @@ describe('Run tests against gRPC server', async function () {
7176
}
7277
if (retryCount === MAX_RETRIES) {
7378
throw new Error(
74-
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`
79+
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`,
7580
);
7681
}
7782
});

0 commit comments

Comments
 (0)