1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | import { Metadata } from './metadata';
|
19 |
|
20 | export interface CallMetadataOptions {
|
21 | service_url: string;
|
22 | }
|
23 |
|
24 | export type CallMetadataGenerator = (
|
25 | options: CallMetadataOptions,
|
26 | cb: (err: Error | null, metadata?: Metadata) => void
|
27 | ) => void;
|
28 |
|
29 |
|
30 |
|
31 | export interface OldOAuth2Client {
|
32 | getRequestMetadata: (
|
33 | url: string,
|
34 | callback: (
|
35 | err: Error | null,
|
36 | headers?: {
|
37 | [index: string]: string;
|
38 | }
|
39 | ) => void
|
40 | ) => void;
|
41 | }
|
42 |
|
43 | export interface CurrentOAuth2Client {
|
44 | getRequestHeaders: (url?: string) => Promise<{ [index: string]: string }>;
|
45 | }
|
46 |
|
47 | export type OAuth2Client = OldOAuth2Client | CurrentOAuth2Client;
|
48 |
|
49 | function isCurrentOauth2Client(
|
50 | client: OAuth2Client
|
51 | ): client is CurrentOAuth2Client {
|
52 | return (
|
53 | 'getRequestHeaders' in client &&
|
54 | typeof client.getRequestHeaders === 'function'
|
55 | );
|
56 | }
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | export abstract class CallCredentials {
|
63 | |
64 |
|
65 |
|
66 |
|
67 | abstract generateMetadata(options: CallMetadataOptions): Promise<Metadata>;
|
68 | |
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | abstract compose(callCredentials: CallCredentials): CallCredentials;
|
75 |
|
76 | |
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | abstract _equals(other: CallCredentials): boolean;
|
83 |
|
84 | |
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 | static createFromMetadataGenerator(
|
92 | metadataGenerator: CallMetadataGenerator
|
93 | ): CallCredentials {
|
94 | return new SingleCallCredentials(metadataGenerator);
|
95 | }
|
96 |
|
97 | |
98 |
|
99 |
|
100 |
|
101 |
|
102 | static createFromGoogleCredential(
|
103 | googleCredentials: OAuth2Client
|
104 | ): CallCredentials {
|
105 | return CallCredentials.createFromMetadataGenerator((options, callback) => {
|
106 | let getHeaders: Promise<{ [index: string]: string }>;
|
107 | if (isCurrentOauth2Client(googleCredentials)) {
|
108 | getHeaders = googleCredentials.getRequestHeaders(options.service_url);
|
109 | } else {
|
110 | getHeaders = new Promise((resolve, reject) => {
|
111 | googleCredentials.getRequestMetadata(
|
112 | options.service_url,
|
113 | (err, headers) => {
|
114 | if (err) {
|
115 | reject(err);
|
116 | return;
|
117 | }
|
118 | resolve(headers);
|
119 | }
|
120 | );
|
121 | });
|
122 | }
|
123 | getHeaders.then(
|
124 | (headers) => {
|
125 | const metadata = new Metadata();
|
126 | for (const key of Object.keys(headers)) {
|
127 | metadata.add(key, headers[key]);
|
128 | }
|
129 | callback(null, metadata);
|
130 | },
|
131 | (err) => {
|
132 | callback(err);
|
133 | }
|
134 | );
|
135 | });
|
136 | }
|
137 |
|
138 | static createEmpty(): CallCredentials {
|
139 | return new EmptyCallCredentials();
|
140 | }
|
141 | }
|
142 |
|
143 | class ComposedCallCredentials extends CallCredentials {
|
144 | constructor(private creds: CallCredentials[]) {
|
145 | super();
|
146 | }
|
147 |
|
148 | async generateMetadata(options: CallMetadataOptions): Promise<Metadata> {
|
149 | const base: Metadata = new Metadata();
|
150 | const generated: Metadata[] = await Promise.all(
|
151 | this.creds.map((cred) => cred.generateMetadata(options))
|
152 | );
|
153 | for (const gen of generated) {
|
154 | base.merge(gen);
|
155 | }
|
156 | return base;
|
157 | }
|
158 |
|
159 | compose(other: CallCredentials): CallCredentials {
|
160 | return new ComposedCallCredentials(this.creds.concat([other]));
|
161 | }
|
162 |
|
163 | _equals(other: CallCredentials): boolean {
|
164 | if (this === other) {
|
165 | return true;
|
166 | }
|
167 | if (other instanceof ComposedCallCredentials) {
|
168 | return this.creds.every((value, index) =>
|
169 | value._equals(other.creds[index])
|
170 | );
|
171 | } else {
|
172 | return false;
|
173 | }
|
174 | }
|
175 | }
|
176 |
|
177 | class SingleCallCredentials extends CallCredentials {
|
178 | constructor(private metadataGenerator: CallMetadataGenerator) {
|
179 | super();
|
180 | }
|
181 |
|
182 | generateMetadata(options: CallMetadataOptions): Promise<Metadata> {
|
183 | return new Promise<Metadata>((resolve, reject) => {
|
184 | this.metadataGenerator(options, (err, metadata) => {
|
185 | if (metadata !== undefined) {
|
186 | resolve(metadata);
|
187 | } else {
|
188 | reject(err);
|
189 | }
|
190 | });
|
191 | });
|
192 | }
|
193 |
|
194 | compose(other: CallCredentials): CallCredentials {
|
195 | return new ComposedCallCredentials([this, other]);
|
196 | }
|
197 |
|
198 | _equals(other: CallCredentials): boolean {
|
199 | if (this === other) {
|
200 | return true;
|
201 | }
|
202 | if (other instanceof SingleCallCredentials) {
|
203 | return this.metadataGenerator === other.metadataGenerator;
|
204 | } else {
|
205 | return false;
|
206 | }
|
207 | }
|
208 | }
|
209 |
|
210 | class EmptyCallCredentials extends CallCredentials {
|
211 | generateMetadata(options: CallMetadataOptions): Promise<Metadata> {
|
212 | return Promise.resolve(new Metadata());
|
213 | }
|
214 |
|
215 | compose(other: CallCredentials): CallCredentials {
|
216 | return other;
|
217 | }
|
218 |
|
219 | _equals(other: CallCredentials): boolean {
|
220 | return other instanceof EmptyCallCredentials;
|
221 | }
|
222 | }
|
223 |
|
\ | No newline at end of file |