UNPKG

6.79 kBJavaScriptView Raw
1"use strict";
2// Copyright 2015 Google LLC
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15Object.defineProperty(exports, "__esModule", { value: true });
16exports.Service = exports.DEFAULT_PROJECT_ID_TOKEN = void 0;
17/*!
18 * @module common/service
19 */
20const arrify = require("arrify");
21const extend = require("extend");
22const util_1 = require("./util");
23exports.DEFAULT_PROJECT_ID_TOKEN = '{{projectId}}';
24class Service {
25 /**
26 * Service is a base class, meant to be inherited from by a "service," like
27 * BigQuery or Storage.
28 *
29 * This handles making authenticated requests by exposing a `makeReq_`
30 * function.
31 *
32 * @constructor
33 * @alias module:common/service
34 *
35 * @param {object} config - Configuration object.
36 * @param {string} config.baseUrl - The base URL to make API requests to.
37 * @param {string[]} config.scopes - The scopes required for the request.
38 * @param {object=} options - [Configuration object](#/docs).
39 */
40 constructor(config, options = {}) {
41 this.baseUrl = config.baseUrl;
42 this.apiEndpoint = config.apiEndpoint;
43 this.timeout = options.timeout;
44 this.globalInterceptors = arrify(options.interceptors_);
45 this.interceptors = [];
46 this.packageJson = config.packageJson;
47 this.projectId = options.projectId || exports.DEFAULT_PROJECT_ID_TOKEN;
48 this.projectIdRequired = config.projectIdRequired !== false;
49 this.providedUserAgent = options.userAgent;
50 const reqCfg = extend({}, config, {
51 projectIdRequired: this.projectIdRequired,
52 projectId: this.projectId,
53 authClient: options.authClient,
54 credentials: options.credentials,
55 keyFile: options.keyFilename,
56 email: options.email,
57 token: options.token,
58 });
59 this.makeAuthenticatedRequest =
60 util_1.util.makeAuthenticatedRequestFactory(reqCfg);
61 this.authClient = this.makeAuthenticatedRequest.authClient;
62 this.getCredentials = this.makeAuthenticatedRequest.getCredentials;
63 const isCloudFunctionEnv = !!process.env.FUNCTION_NAME;
64 if (isCloudFunctionEnv) {
65 this.interceptors.push({
66 request(reqOpts) {
67 reqOpts.forever = false;
68 return reqOpts;
69 },
70 });
71 }
72 }
73 /**
74 * Return the user's custom request interceptors.
75 */
76 getRequestInterceptors() {
77 // Interceptors should be returned in the order they were assigned.
78 return [].slice
79 .call(this.globalInterceptors)
80 .concat(this.interceptors)
81 .filter(interceptor => typeof interceptor.request === 'function')
82 .map(interceptor => interceptor.request);
83 }
84 getProjectId(callback) {
85 if (!callback) {
86 return this.getProjectIdAsync();
87 }
88 this.getProjectIdAsync().then(p => callback(null, p), callback);
89 }
90 async getProjectIdAsync() {
91 const projectId = await this.authClient.getProjectId();
92 if (this.projectId === exports.DEFAULT_PROJECT_ID_TOKEN && projectId) {
93 this.projectId = projectId;
94 }
95 return this.projectId;
96 }
97 request_(reqOpts, callback) {
98 reqOpts = extend(true, {}, reqOpts, { timeout: this.timeout });
99 const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0;
100 const uriComponents = [this.baseUrl];
101 if (this.projectIdRequired) {
102 if (reqOpts.projectId) {
103 uriComponents.push('projects');
104 uriComponents.push(reqOpts.projectId);
105 }
106 else {
107 uriComponents.push('projects');
108 uriComponents.push(this.projectId);
109 }
110 }
111 uriComponents.push(reqOpts.uri);
112 if (isAbsoluteUrl) {
113 uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri));
114 }
115 reqOpts.uri = uriComponents
116 .map(uriComponent => {
117 const trimSlashesRegex = /^\/*|\/*$/g;
118 return uriComponent.replace(trimSlashesRegex, '');
119 })
120 .join('/')
121 // Some URIs have colon separators.
122 // Bad: https://.../projects/:list
123 // Good: https://.../projects:list
124 .replace(/\/:/g, ':');
125 const requestInterceptors = this.getRequestInterceptors();
126 arrify(reqOpts.interceptors_).forEach(interceptor => {
127 if (typeof interceptor.request === 'function') {
128 requestInterceptors.push(interceptor.request);
129 }
130 });
131 requestInterceptors.forEach(requestInterceptor => {
132 reqOpts = requestInterceptor(reqOpts);
133 });
134 delete reqOpts.interceptors_;
135 const pkg = this.packageJson;
136 let userAgent = util_1.util.getUserAgentFromPackageJson(pkg);
137 if (this.providedUserAgent) {
138 userAgent = `${this.providedUserAgent} ${userAgent}`;
139 }
140 reqOpts.headers = extend({}, reqOpts.headers, {
141 'User-Agent': userAgent,
142 'x-goog-api-client': `gl-node/${process.versions.node} gccl/${pkg.version}`,
143 });
144 if (reqOpts.shouldReturnStream) {
145 return this.makeAuthenticatedRequest(reqOpts);
146 }
147 else {
148 this.makeAuthenticatedRequest(reqOpts, callback);
149 }
150 }
151 /**
152 * Make an authenticated API request.
153 *
154 * @param {object} reqOpts - Request options that are passed to `request`.
155 * @param {string} reqOpts.uri - A URI relative to the baseUrl.
156 * @param {function} callback - The callback function passed to `request`.
157 */
158 request(reqOpts, callback) {
159 Service.prototype.request_.call(this, reqOpts, callback);
160 }
161 /**
162 * Make an authenticated API request.
163 *
164 * @param {object} reqOpts - Request options that are passed to `request`.
165 * @param {string} reqOpts.uri - A URI relative to the baseUrl.
166 */
167 requestStream(reqOpts) {
168 const opts = extend(true, reqOpts, { shouldReturnStream: true });
169 return Service.prototype.request_.call(this, opts);
170 }
171}
172exports.Service = Service;
173//# sourceMappingURL=service.js.map
\No newline at end of file