|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { Metadata } from './metadata'; |
|
|
|
export interface CallMetadataOptions { |
|
service_url: string; |
|
} |
|
|
|
export type CallMetadataGenerator = ( |
|
options: CallMetadataOptions, |
|
cb: (err: Error | null, metadata?: Metadata) => void |
|
) => void; |
|
|
|
|
|
|
|
export interface OldOAuth2Client { |
|
getRequestMetadata: ( |
|
url: string, |
|
callback: ( |
|
err: Error | null, |
|
headers?: { |
|
[index: string]: string; |
|
} |
|
) => void |
|
) => void; |
|
} |
|
|
|
export interface CurrentOAuth2Client { |
|
getRequestHeaders: (url?: string) => Promise<{ [index: string]: string }>; |
|
} |
|
|
|
export type OAuth2Client = OldOAuth2Client | CurrentOAuth2Client; |
|
|
|
function isCurrentOauth2Client( |
|
client: OAuth2Client |
|
): client is CurrentOAuth2Client { |
|
return ( |
|
'getRequestHeaders' in client && |
|
typeof client.getRequestHeaders === 'function' |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export abstract class CallCredentials { |
|
|
|
|
|
|
|
|
|
abstract generateMetadata(options: CallMetadataOptions): Promise<Metadata>; |
|
|
|
|
|
|
|
|
|
|
|
|
|
abstract compose(callCredentials: CallCredentials): CallCredentials; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abstract _equals(other: CallCredentials): boolean; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static createFromMetadataGenerator( |
|
metadataGenerator: CallMetadataGenerator |
|
): CallCredentials { |
|
return new SingleCallCredentials(metadataGenerator); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
static createFromGoogleCredential( |
|
googleCredentials: OAuth2Client |
|
): CallCredentials { |
|
return CallCredentials.createFromMetadataGenerator((options, callback) => { |
|
let getHeaders: Promise<{ [index: string]: string }>; |
|
if (isCurrentOauth2Client(googleCredentials)) { |
|
getHeaders = googleCredentials.getRequestHeaders(options.service_url); |
|
} else { |
|
getHeaders = new Promise((resolve, reject) => { |
|
googleCredentials.getRequestMetadata( |
|
options.service_url, |
|
(err, headers) => { |
|
if (err) { |
|
reject(err); |
|
return; |
|
} |
|
if (!headers) { |
|
reject(new Error('Headers not set by metadata plugin')); |
|
return; |
|
} |
|
resolve(headers); |
|
} |
|
); |
|
}); |
|
} |
|
getHeaders.then( |
|
headers => { |
|
const metadata = new Metadata(); |
|
for (const key of Object.keys(headers)) { |
|
metadata.add(key, headers[key]); |
|
} |
|
callback(null, metadata); |
|
}, |
|
err => { |
|
callback(err); |
|
} |
|
); |
|
}); |
|
} |
|
|
|
static createEmpty(): CallCredentials { |
|
return new EmptyCallCredentials(); |
|
} |
|
} |
|
|
|
class ComposedCallCredentials extends CallCredentials { |
|
constructor(private creds: CallCredentials[]) { |
|
super(); |
|
} |
|
|
|
async generateMetadata(options: CallMetadataOptions): Promise<Metadata> { |
|
const base: Metadata = new Metadata(); |
|
const generated: Metadata[] = await Promise.all( |
|
this.creds.map(cred => cred.generateMetadata(options)) |
|
); |
|
for (const gen of generated) { |
|
base.merge(gen); |
|
} |
|
return base; |
|
} |
|
|
|
compose(other: CallCredentials): CallCredentials { |
|
return new ComposedCallCredentials(this.creds.concat([other])); |
|
} |
|
|
|
_equals(other: CallCredentials): boolean { |
|
if (this === other) { |
|
return true; |
|
} |
|
if (other instanceof ComposedCallCredentials) { |
|
return this.creds.every((value, index) => |
|
value._equals(other.creds[index]) |
|
); |
|
} else { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
class SingleCallCredentials extends CallCredentials { |
|
constructor(private metadataGenerator: CallMetadataGenerator) { |
|
super(); |
|
} |
|
|
|
generateMetadata(options: CallMetadataOptions): Promise<Metadata> { |
|
return new Promise<Metadata>((resolve, reject) => { |
|
this.metadataGenerator(options, (err, metadata) => { |
|
if (metadata !== undefined) { |
|
resolve(metadata); |
|
} else { |
|
reject(err); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
compose(other: CallCredentials): CallCredentials { |
|
return new ComposedCallCredentials([this, other]); |
|
} |
|
|
|
_equals(other: CallCredentials): boolean { |
|
if (this === other) { |
|
return true; |
|
} |
|
if (other instanceof SingleCallCredentials) { |
|
return this.metadataGenerator === other.metadataGenerator; |
|
} else { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
class EmptyCallCredentials extends CallCredentials { |
|
generateMetadata(options: CallMetadataOptions): Promise<Metadata> { |
|
return Promise.resolve(new Metadata()); |
|
} |
|
|
|
compose(other: CallCredentials): CallCredentials { |
|
return other; |
|
} |
|
|
|
_equals(other: CallCredentials): boolean { |
|
return other instanceof EmptyCallCredentials; |
|
} |
|
} |
|
|