Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Update google-auth-library to v10 #1702

Merged
merged 11 commits into from
Feb 27, 2025
5 changes: 1 addition & 4 deletions gax/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/long": "^5.0.0",
"abort-controller": "^3.0.0",
"duplexify": "^4.1.3",
"google-auth-library": "^9.15.1",
"google-auth-library": "^10.0.0-rc.1",
"node-fetch": "^3.3.2",
"object-hash": "^3.0.0",
"proto3-json-serializer": "^3.0.0",
Expand All @@ -27,15 +27,12 @@
"@types/mocha": "^10.0.10",
"@types/ncp": "^2.0.8",
"@types/node": "^20.5.0",
"@types/node-fetch": "^2.6.12",
"@types/object-hash": "^3.0.6",
"@types/proxyquire": "^1.3.31",
"@types/pumpify": "^1.4.4",
"@types/sinon": "^17.0.3",
"@types/uglify-js": "^3.17.5",
"assert": "^2.1.0",
"c8": "^10.1.3",
"cheerio": "^1.0.0",
"codecov": "^3.8.3",
"execa": "^5.0.0",
"glob": "10.4.5",
Expand Down
67 changes: 32 additions & 35 deletions gax/src/fallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,7 @@ import * as protobuf from 'protobufjs';
import * as gax from './gax';
import * as routingHeader from './routingHeader';
import {Status} from './status';
import {
GoogleAuth,
OAuth2Client,
Compute,
JWT,
UserRefreshClient,
GoogleAuthOptions,
BaseExternalAccountClient,
} from 'google-auth-library';
import {GoogleAuth, AuthClient} from 'google-auth-library';
import {OperationsClientBuilder} from './operationsClient';
import type {GrpcClientOptions, ClientStubOptions} from './grpc';
import {GaxCall, GRPCCall} from './apitypes';
Expand Down Expand Up @@ -85,15 +77,16 @@ export interface ServiceMethods {
[name: string]: protobuf.Method;
}

export type AuthClient =
| OAuth2Client
| Compute
| JWT
| UserRefreshClient
| BaseExternalAccountClient;
/**
* @deprecated use `GoogleAuth` here instead
*/
type deprecatedAuthClientAlias = AuthClient;

export class GrpcClient {
auth?: OAuth2Client | GoogleAuth;
auth?: GoogleAuth<AuthClient> | deprecatedAuthClientAlias;
/**
* @deprecated use {@link GrpcClient.auth} instead
*/
authClient?: AuthClient;
fallback: boolean;
grpcVersion: string;
Expand All @@ -114,33 +107,36 @@ export class GrpcClient {
* gRPC-fallback version of GrpcClient
* Implements GrpcClient API for a browser using grpc-fallback protocol (sends serialized protobuf to HTTP/1 $rpc endpoint).
*
* @param {Object=} options.auth - An instance of OAuth2Client to use in browser, or an instance of GoogleAuth from google-auth-library
* to use in Node.js. Required for browser, optional for Node.js.
* @constructor
* @param options {@link GrpcClientOptions}
*/

constructor(
options: (GrpcClientOptions | {auth: OAuth2Client}) & {
options: (
| GrpcClientOptions
| {
/**
* @deprecated - use `authClient` for `AuthClient`s instead
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GrpcClientOptions currently includes this parameter, and with the correct name; authClient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should create a follow-up to clean this up in the next major to avoid confusion

*/
auth: AuthClient;
}
) & {
/**
* Fallback mode to use instead of gRPC.
* A string is accepted for compatibility, all non-empty string values enable the HTTP REST fallback.
*/
fallback?: boolean | string;
} = {},
) {
if (!isNodeJS()) {
if (!options.auth) {
throw new Error(
JSON.stringify(options) +
'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.',
);
}
this.auth = options.auth as OAuth2Client;
if (options.auth) {
this.auth = options.auth;
} else if ('authClient' in options) {
this.auth = options.authClient;
} else {
this.auth =
(options.auth as GoogleAuth) ||
new GoogleAuth(options as GoogleAuthOptions);
this.auth = new GoogleAuth({
authClient: options.auth,
...options,
});
}

this.fallback = options.fallback ? true : false;
this.grpcVersion = require('../../package.json').version;
this.httpRules = (options as GrpcClientOptions).httpRules;
Expand Down Expand Up @@ -266,7 +262,7 @@ export class GrpcClient {

/**
* gRPC-fallback version of createStub
* Creates a gRPC-fallback stub with authentication headers built from supplied OAuth2Client instance
* Creates a gRPC-fallback stub with authentication headers built from supplied `AuthClient` instance
*
* @param {function} CreateStub - The constructor function of the stub.
* @param {Object} service - A protobufjs Service object (as returned by lookupService)
Expand All @@ -284,7 +280,7 @@ export class GrpcClient {
) {
if (!this.authClient) {
if (this.auth && 'getClient' in this.auth) {
this.authClient = (await this.auth.getClient()) as AuthClient;
this.authClient = await this.auth.getClient();
} else if (this.auth && 'getRequestHeaders' in this.auth) {
this.authClient = this.auth;
}
Expand Down Expand Up @@ -342,7 +338,7 @@ export class GrpcClient {
protocol,
servicePath,
servicePort,
this.authClient,
this.auth || this.authClient,
encoder,
decoder,
this.numericEnums,
Expand Down Expand Up @@ -425,6 +421,7 @@ export function createApiCall(
};
}
if (descriptor && 'streaming' in descriptor && !isNodeJS()) {
// TODO: with `fetch` this functionality is available in the browser...
return () => {
throw new Error(
'Server streaming over the REST transport is only supported in Node.js.',
Expand Down
23 changes: 12 additions & 11 deletions gax/src/fallbackServiceStub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import type {
RequestInit,
} from 'node-fetch' with {'resolution-mode': 'import'};
import {AbortController as NodeAbortController} from 'abort-controller';

import {AuthClient, GoogleAuth, gaxios} from 'google-auth-library';

import type nodeFetch from 'node-fetch' with {'resolution-mode': 'import'};
import {hasWindowFetch, hasAbortController, isNodeJS} from './featureDetection';
import {AuthClient} from './fallback';
import {StreamArrayParser} from './streamArrayParser';
import {pipeline, PipelineSource} from 'stream';
import type {Agent as HttpAgent} from 'http';
Expand All @@ -38,7 +40,9 @@ interface NodeFetchType {
// Node.js before v19 does not enable keepalive by default.
// We'll try to enable it very carefully to make sure we don't break possible non-Node use cases.
// TODO: remove this after Node 18 is EOL.
// More info: https://github.com/node-fetch/node-fetch#custom-agent
// More info:
// - https://github.com/node-fetch/node-fetch#custom-agent
// - https://github.com/googleapis/gax-nodejs/pull/1534
let agentOption:
| ((parsedUrl: {protocol: string}) => HttpAgent | HttpsAgent)
| null = null;
Expand Down Expand Up @@ -68,7 +72,7 @@ export interface FallbackServiceStub {
export type FetchParametersMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

export interface FetchParameters {
headers: {[key: string]: string};
headers: {[key: string]: string} | Headers;
body: Buffer | Uint8Array | string;
method: FetchParametersMethod;
url: string;
Expand All @@ -79,7 +83,7 @@ export function generateServiceStub(
protocol: string,
servicePath: string,
servicePort: number,
authClient: AuthClient,
auth: GoogleAuth | AuthClient,
requestEncoder: (
rpc: protobuf.Method,
protocol: string,
Expand Down Expand Up @@ -147,20 +151,17 @@ export function generateServiceStub(
const cancelSignal = cancelController.signal as AbortSignal;
let cancelRequested = false;
const url = fetchParameters.url;
const headers = fetchParameters.headers;
const headers = new Headers(fetchParameters.headers);
for (const key of Object.keys(options)) {
headers[key] = options[key][0];
headers.set(key, options[key][0]);
}
const streamArrayParser = new StreamArrayParser(rpc);

authClient
auth
.getRequestHeaders()
.then(authHeader => {
const fetchRequest: RequestInit = {
headers: {
...authHeader,
...headers,
},
headers: gaxios.Gaxios.mergeHeaders(authHeader, headers) as {},
body: fetchParameters.body as string | Buffer | undefined,
method: fetchParameters.method,
signal: cancelSignal,
Expand Down
12 changes: 11 additions & 1 deletion gax/src/grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,17 @@ export class GrpcClient {
const client = await this.auth.getClient();
const credentials = grpc.credentials.combineChannelCredentials(
sslCreds,
grpc.credentials.createFromGoogleCredential(client),
grpc.credentials.createFromGoogleCredential({
// the `grpc` package does not support the `Headers` object yet
getRequestHeaders: async (url?: string | URL) => {
const headers = await client.getRequestHeaders(url);
const genericHeadersObject: Record<string, string> = {};

headers.forEach((value, key) => (genericHeadersObject[key] = value));

return genericHeadersObject;
},
}),
);
return credentials;
}
Expand Down
4 changes: 2 additions & 2 deletions gax/src/iamService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as gax from './gax';
import type {GrpcClient, ClientStubOptions} from './grpc';
import type {GrpcClient as FallbackGrpcClient} from './fallback';
import {createApiCall} from './createApiCall';
import {GoogleAuth, OAuth2Client} from 'google-auth-library';
import {GoogleAuth, AuthClient} from 'google-auth-library';
import {ProjectIdCallback} from 'google-auth-library/build/src/auth/googleauth';
import * as routingHeader from './routingHeader';
import * as gapicConfig from './iam_policy_service_client_config.json';
Expand All @@ -40,7 +40,7 @@ export class IamClient {
private _defaults: {[method: string]: gax.CallSettings};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _protos: any;
auth?: GoogleAuth | OAuth2Client;
auth?: GoogleAuth | AuthClient;
descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}};
innerApiCalls: {[name: string]: Function} = {};
iamPolicyStub?: Promise<{[name: string]: Function}>;
Expand Down
2 changes: 2 additions & 0 deletions gax/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import * as operationsClient from './operationsClient';
import * as routingHeader from './routingHeader';

export {GoogleAuth, GoogleAuthOptions} from 'google-auth-library';
export * as googleAuthLibrary from 'google-auth-library';

export {grpc};
export {CancellablePromise, OngoingCall} from './call';
export {createApiCall} from './createApiCall';
Expand Down
4 changes: 2 additions & 2 deletions gax/src/operationsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

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

Expand Down Expand Up @@ -62,7 +62,7 @@ export const ALL_SCOPES: string[] = [];
* @class
*/
export class OperationsClient {
auth?: GoogleAuth | OAuth2Client;
auth?: GoogleAuth | AuthClient;
innerApiCalls: {[name: string]: Function};
descriptor: {[method: string]: PageDescriptor};
operationsStub: Promise<{[method: string]: Function}>;
Expand Down
4 changes: 4 additions & 0 deletions gax/test/browser-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"@types/node": "^20.5.0",
"@types/sinon": "^10.0.13",
"assert": "^2.1.0",
"browserify-zlib": "^0.2.0",
"core-js": "^3.40.0",
"crypto-browserify": "^3.12.1",
"google-gax": "./google-gax.tgz",
"https-browserify": "^1.0.0",
"is-docker": "^2.2.1",
Expand All @@ -39,6 +41,8 @@
"karma-sourcemap-loader": "^0.4.0",
"karma-webpack": "^5.0.1",
"mocha": "^10.0.0",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"puppeteer": "^16.0.0",
"querystring-es3": "^0.2.1",
Expand Down
11 changes: 8 additions & 3 deletions gax/test/browser-test/test/test.endtoend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ function sleep(timeout: number) {

describe('Run tests against gRPC server', async function () {
const authStub = {
getRequestHeaders: async () => {
return new Headers({
Authorization: 'Bearer zzzz',
});
},
getClient: async () => {
return {
getRequestHeaders: async () => {
return {
return new Headers({
Authorization: 'Bearer zzzz',
};
});
},
};
},
Expand Down Expand Up @@ -71,7 +76,7 @@ describe('Run tests against gRPC server', async function () {
}
if (retryCount === MAX_RETRIES) {
throw new Error(
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`,
);
}
});
Expand Down
Loading