UNPKG

13.5 kBJavaScriptView Raw
1"use strict";
2/**
3 * Copyright 2020 Google LLC
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.fallback = exports.protobuf = exports.createApiCall = exports.lro = exports.GrpcClient = exports.defaultToObjectOptions = exports.version = exports.routingHeader = void 0;
19const protobuf = require("protobufjs");
20exports.protobuf = protobuf;
21const gax = require("./gax");
22const routingHeader = require("./routingHeader");
23exports.routingHeader = routingHeader;
24const status_1 = require("./status");
25const google_auth_library_1 = require("google-auth-library");
26const objectHash = require("object-hash");
27const operationsClient_1 = require("./operationsClient");
28const createApiCall_1 = require("./createApiCall");
29const fallbackProto = require("./fallbackProto");
30const fallbackRest = require("./fallbackRest");
31const featureDetection_1 = require("./featureDetection");
32const fallbackServiceStub_1 = require("./fallbackServiceStub");
33var pathTemplate_1 = require("./pathTemplate");
34Object.defineProperty(exports, "PathTemplate", { enumerable: true, get: function () { return pathTemplate_1.PathTemplate; } });
35var gax_1 = require("./gax");
36Object.defineProperty(exports, "CallSettings", { enumerable: true, get: function () { return gax_1.CallSettings; } });
37Object.defineProperty(exports, "constructSettings", { enumerable: true, get: function () { return gax_1.constructSettings; } });
38Object.defineProperty(exports, "RetryOptions", { enumerable: true, get: function () { return gax_1.RetryOptions; } });
39exports.version = require('../../package.json').version + '-fallback';
40var descriptor_1 = require("./descriptor");
41Object.defineProperty(exports, "BundleDescriptor", { enumerable: true, get: function () { return descriptor_1.BundleDescriptor; } });
42Object.defineProperty(exports, "LongrunningDescriptor", { enumerable: true, get: function () { return descriptor_1.LongrunningDescriptor; } });
43Object.defineProperty(exports, "PageDescriptor", { enumerable: true, get: function () { return descriptor_1.PageDescriptor; } });
44Object.defineProperty(exports, "StreamDescriptor", { enumerable: true, get: function () { return descriptor_1.StreamDescriptor; } });
45var streaming_1 = require("./streamingCalls/streaming");
46Object.defineProperty(exports, "StreamType", { enumerable: true, get: function () { return streaming_1.StreamType; } });
47exports.defaultToObjectOptions = {
48 keepCase: false,
49 longs: String,
50 enums: String,
51 defaults: true,
52 oneofs: true,
53};
54const CLIENT_VERSION_HEADER = 'x-goog-api-client';
55class GrpcClient {
56 /**
57 * gRPC-fallback version of GrpcClient
58 * Implements GrpcClient API for a browser using grpc-fallback protocol (sends serialized protobuf to HTTP/1 $rpc endpoint).
59 *
60 * @param {Object=} options.auth - An instance of OAuth2Client to use in browser, or an instance of GoogleAuth from google-auth-library
61 * to use in Node.js. Required for browser, optional for Node.js.
62 * @constructor
63 */
64 constructor(options = {}) {
65 if (!featureDetection_1.isNodeJS()) {
66 if (!options.auth) {
67 throw new Error(JSON.stringify(options) +
68 '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.');
69 }
70 this.auth = options.auth;
71 }
72 else {
73 this.auth =
74 options.auth ||
75 new google_auth_library_1.GoogleAuth(options);
76 }
77 this.fallback = options.fallback !== 'rest' ? 'proto' : 'rest';
78 this.grpcVersion = require('../../package.json').version;
79 }
80 /**
81 * In rare cases users might need to deallocate all memory consumed by loaded protos.
82 * This method will delete the proto cache content.
83 */
84 static clearProtoCache() {
85 GrpcClient.protoCache.clear();
86 }
87 /**
88 * gRPC-fallback version of loadProto
89 * Loads the protobuf root object from a JSON object created from a proto file
90 * @param {Object} jsonObject - A JSON version of a protofile created usin protobuf.js
91 * @returns {Object} Root namespace of proto JSON
92 */
93 loadProto(jsonObject) {
94 const rootObject = protobuf.Root.fromJSON(jsonObject);
95 return rootObject;
96 }
97 loadProtoJSON(json, ignoreCache = false) {
98 const hash = objectHash(json).toString();
99 const cached = GrpcClient.protoCache.get(hash);
100 if (cached && !ignoreCache) {
101 return cached;
102 }
103 const root = protobuf.Root.fromJSON(json);
104 GrpcClient.protoCache.set(hash, root);
105 return root;
106 }
107 static getServiceMethods(service) {
108 const methods = {};
109 for (const [methodName, methodObject] of Object.entries(service.methods)) {
110 const methodNameLowerCamelCase = methodName[0].toLowerCase() + methodName.substring(1);
111 methods[methodNameLowerCamelCase] = methodObject;
112 }
113 return methods;
114 }
115 /**
116 * gRPC-fallback version of constructSettings
117 * A wrapper of {@link constructSettings} function under the gRPC context.
118 *
119 * Most of parameters are common among constructSettings, please take a look.
120 * @param {string} serviceName - The fullly-qualified name of the service.
121 * @param {Object} clientConfig - A dictionary of the client config.
122 * @param {Object} configOverrides - A dictionary of overriding configs.
123 * @param {Object} headers - A dictionary of additional HTTP header name to
124 * its value.
125 * @return {Object} A mapping of method names to CallSettings.
126 */
127 constructSettings(serviceName, clientConfig, configOverrides, headers) {
128 function buildMetadata(abTests, moreHeaders) {
129 const metadata = {};
130 if (!headers) {
131 headers = {};
132 }
133 // Since gRPC expects each header to be an array,
134 // we are doing the same for fallback here.
135 for (const key in headers) {
136 metadata[key] = Array.isArray(headers[key])
137 ? headers[key]
138 : [headers[key]];
139 }
140 // gRPC-fallback request must have 'grpc-web/' in 'x-goog-api-client'
141 const clientVersions = [];
142 if (metadata[CLIENT_VERSION_HEADER] &&
143 metadata[CLIENT_VERSION_HEADER][0]) {
144 clientVersions.push(...metadata[CLIENT_VERSION_HEADER][0].split(' '));
145 }
146 clientVersions.push(`grpc-web/${exports.version}`);
147 metadata[CLIENT_VERSION_HEADER] = [clientVersions.join(' ')];
148 if (!moreHeaders) {
149 return metadata;
150 }
151 for (const key in moreHeaders) {
152 if (key.toLowerCase() !== CLIENT_VERSION_HEADER) {
153 const value = moreHeaders[key];
154 if (Array.isArray(value)) {
155 if (metadata[key] === undefined) {
156 metadata[key] = value;
157 }
158 else {
159 if (Array.isArray(metadata[key])) {
160 metadata[key].push(...value);
161 }
162 else {
163 throw new Error(`Can not add value ${value} to the call metadata.`);
164 }
165 }
166 }
167 else {
168 metadata[key] = [value];
169 }
170 }
171 }
172 return metadata;
173 }
174 return gax.constructSettings(serviceName, clientConfig, configOverrides, status_1.Status, { metadataBuilder: buildMetadata });
175 }
176 /**
177 * gRPC-fallback version of createStub
178 * Creates a gRPC-fallback stub with authentication headers built from supplied OAuth2Client instance
179 *
180 * @param {function} CreateStub - The constructor function of the stub.
181 * @param {Object} service - A protobufjs Service object (as returned by lookupService)
182 * @param {Object} opts - Connection options, as described below.
183 * @param {string} opts.servicePath - The hostname of the API endpoint service.
184 * @param {number} opts.port - The port of the service.
185 * @return {Promise} A promise which resolves to a gRPC-fallback service stub, which is a protobuf.js service stub instance modified to match the gRPC stub API
186 */
187 async createStub(service, opts,
188 // For consistency with createStub in grpc.ts, customServicePath is defined:
189 // eslint-disable-next-line @typescript-eslint/no-unused-vars
190 customServicePath) {
191 if (!this.authClient) {
192 if (this.auth && 'getClient' in this.auth) {
193 this.authClient = await this.auth.getClient();
194 }
195 else if (this.auth && 'getRequestHeaders' in this.auth) {
196 this.authClient = this.auth;
197 }
198 }
199 if (!this.authClient) {
200 throw new Error('No authentication was provided');
201 }
202 service.resolveAll();
203 const methods = GrpcClient.getServiceMethods(service);
204 const protocol = opts.protocol || 'https';
205 let servicePath = opts.servicePath;
206 if (!servicePath &&
207 service.options &&
208 service.options['(google.api.default_host)']) {
209 servicePath = service.options['(google.api.default_host)'];
210 }
211 if (!servicePath) {
212 throw new Error(`Cannot determine service API path for service ${service.name}.`);
213 }
214 let servicePort;
215 const match = servicePath.match(/^(.*):(\d+)$/);
216 if (match) {
217 servicePath = match[1];
218 servicePort = parseInt(match[2]);
219 }
220 if (opts.port) {
221 servicePort = opts.port;
222 }
223 else if (!servicePort) {
224 servicePort = 443;
225 }
226 const encoder = this.fallback === 'rest'
227 ? fallbackRest.encodeRequest
228 : fallbackProto.encodeRequest;
229 const decoder = this.fallback === 'rest'
230 ? fallbackRest.decodeResponse
231 : fallbackProto.decodeResponse;
232 const serviceStub = fallbackServiceStub_1.generateServiceStub(methods, protocol, servicePath, servicePort, this.authClient, encoder, decoder);
233 return serviceStub;
234 }
235}
236exports.GrpcClient = GrpcClient;
237GrpcClient.protoCache = new Map();
238/**
239 * gRPC-fallback version of lro
240 *
241 * @param {Object=} options.auth - An instance of google-auth-library.
242 * @return {Object} A OperationsClientBuilder that will return a OperationsClient
243 */
244function lro(options) {
245 options = Object.assign({ scopes: [] }, options);
246 const gaxGrpc = new GrpcClient(options);
247 return new operationsClient_1.OperationsClientBuilder(gaxGrpc);
248}
249exports.lro = lro;
250/**
251 * gRPC-fallback version of createApiCall
252 *
253 * Converts an rpc call into an API call governed by the settings.
254 *
255 * In typical usage, `func` will be a promise to a callable used to make an rpc
256 * request. This will mostly likely be a bound method from a request stub used
257 * to make an rpc call. It is not a direct function but a Promise instance,
258 * because of its asynchronism (typically, obtaining the auth information).
259 *
260 * The result is a function which manages the API call with the given settings
261 * and the options on the invocation.
262 *
263 * Throws exception on unsupported streaming calls
264 *
265 * @param {Promise<GRPCCall>|GRPCCall} func - is either a promise to be used to make
266 * a bare RPC call, or just a bare RPC call.
267 * @param {CallSettings} settings - provides the settings for this call
268 * @param {Descriptor} descriptor - optionally specify the descriptor for
269 * the method call.
270 * @return {GaxCall} func - a bound method on a request stub used
271 * to make an rpc call.
272 */
273function createApiCall(func, settings, descriptor) {
274 if (descriptor && 'streaming' in descriptor) {
275 return () => {
276 throw new Error('The gRPC-fallback client library (e.g. browser version of the library) currently does not support streaming calls.');
277 };
278 }
279 return createApiCall_1.createApiCall(func, settings, descriptor);
280}
281exports.createApiCall = createApiCall;
282exports.protobufMinimal = require("protobufjs/minimal");
283// Different environments or bundlers may or may not respect "browser" field
284// in package.json (e.g. Electron does not respect it, but if you run the code
285// through webpack first, it will follow the "browser" field).
286// To make it safer and more compatible, let's make sure that if you do
287// const gax = require("google-gax");
288// you can always ask for gax.fallback, regardless of "browser" field being
289// understood or not.
290const fallback = module.exports;
291exports.fallback = fallback;
292//# sourceMappingURL=fallback.js.map
\No newline at end of file