@gravity-ui/gateway 4.1.2-alpha.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist/commonjs → build}/components/grpc.d.ts +4 -4
- package/{dist/commonjs → build}/components/grpc.js +78 -85
- package/{dist/esm → build}/components/mixed.d.ts +4 -4
- package/{dist/commonjs → build}/components/mixed.js +12 -11
- package/{dist/commonjs → build}/components/rest.d.ts +5 -5
- package/{dist/commonjs → build}/components/rest.js +32 -32
- package/{dist/esm → build}/constants.d.ts +2 -2
- package/{dist/commonjs → build}/constants.js +19 -29
- package/{dist/commonjs → build}/index.d.ts +7 -8
- package/{dist/commonjs → build}/index.js +46 -32
- package/{dist/esm → build}/models/common.d.ts +14 -12
- package/{dist/esm → build}/models/context.d.ts +1 -0
- package/build/utils/axios.d.ts +4 -0
- package/{dist/commonjs → build}/utils/axios.js +6 -4
- package/{dist/esm → build}/utils/common.d.ts +3 -3
- package/{dist/commonjs → build}/utils/common.js +8 -7
- package/{dist/commonjs → build}/utils/create-context-api.d.ts +2 -2
- package/{dist/commonjs → build}/utils/create-context-api.js +6 -5
- package/{dist/commonjs → build}/utils/grpc-reflection.js +18 -31
- package/{dist/commonjs → build}/utils/grpc.js +8 -7
- package/build/utils/overrideEndpoints/index.d.ts +2 -0
- package/build/utils/overrideEndpoints/index.js +4 -0
- package/{dist/commonjs → build}/utils/overrideEndpoints/overrideEndpoints.d.ts +1 -1
- package/{dist/commonjs → build}/utils/overrideEndpoints/overrideEndpoints.js +2 -1
- package/{dist/esm → build}/utils/parse-error.d.ts +4 -4
- package/{dist/commonjs → build}/utils/parse-error.js +18 -18
- package/{dist/commonjs → build}/utils/proto-path-resolver.js +17 -23
- package/{dist/commonjs → build}/utils/redact-sensitive-headers.d.ts +2 -1
- package/{dist/commonjs → build}/utils/redact-sensitive-headers.js +2 -1
- package/{dist/commonjs → build}/utils/typed-api.d.ts +1 -1
- package/{dist/commonjs → build}/utils/typed-api.js +2 -1
- package/{dist/commonjs → build}/utils/validate.js +10 -6
- package/package.json +16 -41
- package/dist/commonjs/components/mixed.d.ts +0 -11
- package/dist/commonjs/constants.d.ts +0 -53
- package/dist/commonjs/models/common.d.ts +0 -272
- package/dist/commonjs/models/context.d.ts +0 -22
- package/dist/commonjs/package.json +0 -3
- package/dist/commonjs/utils/axios.d.ts +0 -3
- package/dist/commonjs/utils/common.d.ts +0 -15
- package/dist/commonjs/utils/overrideEndpoints/index.d.ts +0 -2
- package/dist/commonjs/utils/overrideEndpoints/index.js +0 -4
- package/dist/commonjs/utils/package-root.d.ts +0 -1
- package/dist/commonjs/utils/package-root.js +0 -44
- package/dist/commonjs/utils/parse-error.d.ts +0 -30
- package/dist/commonjs/utils/source-dir.d.ts +0 -1
- package/dist/commonjs/utils/source-dir.js +0 -41
- package/dist/esm/components/grpc.d.ts +0 -24
- package/dist/esm/components/grpc.js +0 -641
- package/dist/esm/components/mixed.js +0 -62
- package/dist/esm/components/rest.d.ts +0 -8
- package/dist/esm/components/rest.js +0 -349
- package/dist/esm/constants.js +0 -82
- package/dist/esm/index.d.ts +0 -12
- package/dist/esm/index.js +0 -264
- package/dist/esm/models/common.js +0 -5
- package/dist/esm/models/context.js +0 -1
- package/dist/esm/models/error.d.ts +0 -12
- package/dist/esm/models/error.js +0 -1
- package/dist/esm/package.json +0 -3
- package/dist/esm/utils/axios.d.ts +0 -3
- package/dist/esm/utils/axios.js +0 -23
- package/dist/esm/utils/common.js +0 -38
- package/dist/esm/utils/create-context-api.d.ts +0 -4
- package/dist/esm/utils/create-context-api.js +0 -38
- package/dist/esm/utils/grpc-reflection.d.ts +0 -28
- package/dist/esm/utils/grpc-reflection.js +0 -72
- package/dist/esm/utils/grpc.d.ts +0 -5
- package/dist/esm/utils/grpc.js +0 -39
- package/dist/esm/utils/overrideEndpoints/index.d.ts +0 -2
- package/dist/esm/utils/overrideEndpoints/index.js +0 -2
- package/dist/esm/utils/overrideEndpoints/overrideEndpoints.d.ts +0 -17
- package/dist/esm/utils/overrideEndpoints/overrideEndpoints.js +0 -96
- package/dist/esm/utils/package-root.d.ts +0 -1
- package/dist/esm/utils/package-root.js +0 -8
- package/dist/esm/utils/parse-error.js +0 -210
- package/dist/esm/utils/proto-path-resolver.d.ts +0 -2
- package/dist/esm/utils/proto-path-resolver.js +0 -23
- package/dist/esm/utils/redact-sensitive-headers.d.ts +0 -3
- package/dist/esm/utils/redact-sensitive-headers.js +0 -12
- package/dist/esm/utils/source-dir.d.ts +0 -1
- package/dist/esm/utils/source-dir.js +0 -4
- package/dist/esm/utils/typed-api.d.ts +0 -2
- package/dist/esm/utils/typed-api.js +0 -3
- package/dist/esm/utils/validate.d.ts +0 -4
- package/dist/esm/utils/validate.js +0 -47
- /package/bin/{patch.cjs → patch.js} +0 -0
- /package/{dist/commonjs → build}/models/common.js +0 -0
- /package/{dist/commonjs → build}/models/context.js +0 -0
- /package/{dist/commonjs → build}/models/error.d.ts +0 -0
- /package/{dist/commonjs → build}/models/error.js +0 -0
- /package/{dist/commonjs → build}/utils/grpc-reflection.d.ts +0 -0
- /package/{dist/commonjs → build}/utils/grpc.d.ts +0 -0
- /package/{dist/commonjs → build}/utils/proto-path-resolver.d.ts +0 -0
- /package/{dist/commonjs → build}/utils/validate.d.ts +0 -0
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as grpc from '@grpc/grpc-js';
|
|
2
|
-
import * as protobufjs from 'protobufjs';
|
|
3
|
-
import type * as descriptor from 'protobufjs/ext/descriptor';
|
|
4
|
-
import { ApiActionConfig, ApiServiceGrpcActionConfig, EndpointsConfig, GatewayApiOptions } from '../models/common.js';
|
|
5
|
-
import { GatewayContext } from '../models/context.js';
|
|
6
|
-
import { AppErrorConstructor } from '../models/error.js';
|
|
7
|
-
declare module 'protobufjs' {
|
|
8
|
-
interface Root {
|
|
9
|
-
toDescriptor(protoVersion: string): protobufjs.Message<descriptor.IFileDescriptorSet> & descriptor.IFileDescriptorSet;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
interface CredentialsMap {
|
|
13
|
-
insecure: grpc.ChannelCredentials;
|
|
14
|
-
secure: grpc.ChannelCredentials;
|
|
15
|
-
secureWithoutRootCert: grpc.ChannelCredentials;
|
|
16
|
-
}
|
|
17
|
-
export interface GrpcContext {
|
|
18
|
-
root: protobufjs.Root;
|
|
19
|
-
credentials: CredentialsMap;
|
|
20
|
-
}
|
|
21
|
-
export declare function createRoot(includeGrpcPaths?: string[]): protobufjs.Root;
|
|
22
|
-
export declare function getCredentialsMap(caCertificatePath?: string | null): CredentialsMap;
|
|
23
|
-
export declare function createGrpcAction<Context extends GatewayContext>({ root, credentials }: GrpcContext, endpoints: EndpointsConfig | undefined, config: ApiServiceGrpcActionConfig<Context, any, any>, serviceKey: string, actionName: string, options: GatewayApiOptions<Context>, ErrorConstructor: AppErrorConstructor): (actionConfig: ApiActionConfig<Context, any, any>) => Promise<import("../models/common.js").GatewayActionClientStreamResponse<any> | import("../models/common.js").GatewayActionServerStreamResponse<any> | import("../models/common.js").GatewayActionDuplexStreamResponse<any> | import("../models/common.js").GatewayActionUnaryResponse<any>>;
|
|
24
|
-
export {};
|
|
@@ -1,641 +0,0 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import * as grpc from '@grpc/grpc-js';
|
|
5
|
-
import * as protoLoader from '@grpc/proto-loader';
|
|
6
|
-
import _ from 'lodash';
|
|
7
|
-
import sizeof from 'object-sizeof';
|
|
8
|
-
import * as protobufjs from 'protobufjs';
|
|
9
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
-
import { DEFAULT_GRPC_OPTIONS, DEFAULT_LANG_HEADER, DEFAULT_PROTO_LOADER_OPTIONS, DEFAULT_PROXY_HEADERS, DEFAULT_TIMEOUT, Lang, VERSION, } from '../constants.js';
|
|
11
|
-
import { GrpcReflection, } from '../models/common.js';
|
|
12
|
-
import { getHeadersFromMetadata, handleError, isExtendedActionEndpoint, isExtendedGrpcActionEndpoint, sanitizeDebugHeaders, } from '../utils/common.js';
|
|
13
|
-
import { getCachedReflectionRoot, getReflectionRoot } from '../utils/grpc-reflection.js';
|
|
14
|
-
import { decodeAnyMessageRecursively, isRecreateServiceError, isRetryableError, } from '../utils/grpc.js';
|
|
15
|
-
import { packageRoot } from '../utils/package-root.js';
|
|
16
|
-
import { GrpcError, grpcErrorFactory, isGrpcError, parseGrpcError } from '../utils/parse-error.js';
|
|
17
|
-
import { patchProtoPathResolver } from '../utils/proto-path-resolver.js';
|
|
18
|
-
import { redactSensitiveHeaders } from '../utils/redact-sensitive-headers.js';
|
|
19
|
-
import { validateArgs } from '../utils/validate.js';
|
|
20
|
-
const grpcLoaderOptions = Object.assign(Object.assign({}, DEFAULT_PROTO_LOADER_OPTIONS), { includeDirs: [path.join(packageRoot, 'proto')] });
|
|
21
|
-
export function createRoot(includeGrpcPaths) {
|
|
22
|
-
const root = new protobufjs.Root();
|
|
23
|
-
root.loadSync(path.resolve(packageRoot, 'proto/google/rpc/code.proto'));
|
|
24
|
-
root.loadSync(path.resolve(packageRoot, 'proto/google/rpc/error_details.proto'));
|
|
25
|
-
root.loadSync(path.resolve(packageRoot, 'proto/google/rpc/status.proto'));
|
|
26
|
-
// Load well-known internal protobufjs types
|
|
27
|
-
root.loadSync('google/protobuf/struct.proto');
|
|
28
|
-
root.loadSync('google/protobuf/wrappers.proto');
|
|
29
|
-
grpcLoaderOptions.includeDirs = [...grpcLoaderOptions.includeDirs, ...(includeGrpcPaths !== null && includeGrpcPaths !== void 0 ? includeGrpcPaths : [])];
|
|
30
|
-
patchProtoPathResolver(root, grpcLoaderOptions.includeDirs);
|
|
31
|
-
return root;
|
|
32
|
-
}
|
|
33
|
-
export function getCredentialsMap(caCertificatePath) {
|
|
34
|
-
let certificate;
|
|
35
|
-
if (caCertificatePath && fs.existsSync(caCertificatePath)) {
|
|
36
|
-
certificate = fs.readFileSync(caCertificatePath);
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
secure: grpc.ChannelCredentials.createSsl(certificate),
|
|
40
|
-
secureWithoutRootCert: grpc.ChannelCredentials.createSsl(),
|
|
41
|
-
insecure: grpc.ChannelCredentials.createInsecure(),
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function decodeResponse(response, packageRoot, ctx, encodedFields = [], ErrorConstructor, decodeAnyMessageProtoLoaderOptions) {
|
|
45
|
-
const systemFields = ['metadata', 'response', 'error.details'];
|
|
46
|
-
[...systemFields, ...encodedFields].forEach((fieldName) => {
|
|
47
|
-
try {
|
|
48
|
-
const parsedFieldName = fieldName.replace(/\.\*$/, '');
|
|
49
|
-
const fieldValue = _.get(response, parsedFieldName);
|
|
50
|
-
if (fieldValue) {
|
|
51
|
-
_.set(response, parsedFieldName, decodeAnyMessageRecursively(packageRoot, fieldValue, decodeAnyMessageProtoLoaderOptions));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
handleError(ErrorConstructor, error, ctx, 'Message decoding failed', { fieldName });
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
function createMetadata({ options, actionConfig, config, params, serviceName, ctx, }) {
|
|
60
|
-
var _a;
|
|
61
|
-
const { headers, requestId, authArgs } = actionConfig;
|
|
62
|
-
const proxyHeaders = [...DEFAULT_PROXY_HEADERS];
|
|
63
|
-
let metadata = {
|
|
64
|
-
'x-request-id': requestId,
|
|
65
|
-
'accept-language': headers[DEFAULT_LANG_HEADER] || Lang.Ru,
|
|
66
|
-
};
|
|
67
|
-
if (typeof options.proxyHeaders === 'function') {
|
|
68
|
-
Object.assign(metadata, options.proxyHeaders(Object.assign({}, headers), 'grpc'));
|
|
69
|
-
}
|
|
70
|
-
else if (Array.isArray(options.proxyHeaders)) {
|
|
71
|
-
proxyHeaders.push(...options.proxyHeaders);
|
|
72
|
-
}
|
|
73
|
-
if (typeof config.proxyHeaders === 'function') {
|
|
74
|
-
Object.assign(metadata, config.proxyHeaders(Object.assign({}, headers), 'grpc'));
|
|
75
|
-
}
|
|
76
|
-
else if (Array.isArray(config.proxyHeaders)) {
|
|
77
|
-
proxyHeaders.push(...config.proxyHeaders);
|
|
78
|
-
}
|
|
79
|
-
for (const headerName of proxyHeaders) {
|
|
80
|
-
if (metadata[headerName] === undefined) {
|
|
81
|
-
metadata[headerName] = headers[headerName];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const authHeaders = ((_a = config.getAuthHeaders) !== null && _a !== void 0 ? _a : options.getAuthHeaders)({
|
|
85
|
-
actionType: 'grpc',
|
|
86
|
-
serviceName,
|
|
87
|
-
requestHeaders: headers,
|
|
88
|
-
authArgs,
|
|
89
|
-
});
|
|
90
|
-
Object.assign(metadata, authHeaders);
|
|
91
|
-
if (config.idempotency) {
|
|
92
|
-
const idempotencyKey = headers['idempotency-key'] || uuidv4();
|
|
93
|
-
Object.assign(metadata, { 'idempotency-key': idempotencyKey });
|
|
94
|
-
}
|
|
95
|
-
const { headers: actionHeaders = null } = params !== null && params !== void 0 ? params : {};
|
|
96
|
-
if (actionHeaders) {
|
|
97
|
-
Object.keys(actionHeaders).forEach((key) => {
|
|
98
|
-
metadata[key] = actionHeaders[key];
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
metadata = _.omitBy(Object.assign(Object.assign({}, ctx.getMetadata()), metadata), _.isUndefined);
|
|
102
|
-
const serviceMetadata = new grpc.Metadata();
|
|
103
|
-
Object.keys(metadata).forEach((key) => {
|
|
104
|
-
if (key) {
|
|
105
|
-
serviceMetadata.add(key, metadata[key]);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
return serviceMetadata;
|
|
109
|
-
}
|
|
110
|
-
function createActionEndpoint(endpointData) {
|
|
111
|
-
return isExtendedActionEndpoint(endpointData) ? endpointData.path : endpointData;
|
|
112
|
-
}
|
|
113
|
-
const packageObjectsMap = new Map();
|
|
114
|
-
const serviceInstancesMap = {};
|
|
115
|
-
const reflectionServiceInstancesMap = {};
|
|
116
|
-
function clearInstancesCache(service, instancesMap, cachePath, closeTimeout, ctx) {
|
|
117
|
-
const cachedService = _.get(instancesMap, cachePath);
|
|
118
|
-
if (cachedService !== service) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
// Remove cached service instance
|
|
122
|
-
_.unset(instancesMap, cachePath);
|
|
123
|
-
// Try to close service connection (prevent memory leak)
|
|
124
|
-
// Bug in node >= 18.15.0 https://github.com/grpc/grpc-node/issues/2091
|
|
125
|
-
// use setTimeout
|
|
126
|
-
Promise.resolve(cachedService).then((client) => {
|
|
127
|
-
setTimeout(() => {
|
|
128
|
-
var _a;
|
|
129
|
-
try {
|
|
130
|
-
(_a = client === null || client === void 0 ? void 0 : client.close) === null || _a === void 0 ? void 0 : _a.call(client);
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
ctx.logError('Failed to close connection during clearing instances cache', error, {
|
|
134
|
-
cachePath,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}, closeTimeout);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
function getChannelCredential(config, endpointData, credentials) {
|
|
141
|
-
let endpointInsecure;
|
|
142
|
-
let endpointSecureWithoutRootCert;
|
|
143
|
-
if (isExtendedGrpcActionEndpoint(endpointData)) {
|
|
144
|
-
endpointInsecure = endpointData === null || endpointData === void 0 ? void 0 : endpointData.insecure;
|
|
145
|
-
endpointSecureWithoutRootCert = endpointData === null || endpointData === void 0 ? void 0 : endpointData.secureWithoutRootCert;
|
|
146
|
-
}
|
|
147
|
-
const isInsecure = config.insecure || endpointInsecure;
|
|
148
|
-
const isSecureWithoutRootCert = config.secureWithoutRootCert || endpointSecureWithoutRootCert;
|
|
149
|
-
let creds = credentials.secure;
|
|
150
|
-
if (isInsecure) {
|
|
151
|
-
creds = credentials.insecure;
|
|
152
|
-
}
|
|
153
|
-
else if (isSecureWithoutRootCert) {
|
|
154
|
-
creds = credentials.secureWithoutRootCert;
|
|
155
|
-
}
|
|
156
|
-
return creds;
|
|
157
|
-
}
|
|
158
|
-
const reflectionCacheStatusMap = {};
|
|
159
|
-
function needRefreshCache(actionEndpoint, protoKey, reflectionRefreshSec) {
|
|
160
|
-
const cacheStatus = _.get(reflectionCacheStatusMap, [protoKey, actionEndpoint]);
|
|
161
|
-
if (!cacheStatus) {
|
|
162
|
-
_.set(reflectionCacheStatusMap, [protoKey, actionEndpoint], {
|
|
163
|
-
time: Date.now() / 1000,
|
|
164
|
-
isRefresh: false,
|
|
165
|
-
});
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
if (cacheStatus.isRefresh) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
return cacheStatus.time + reflectionRefreshSec < Date.now() / 1000;
|
|
172
|
-
}
|
|
173
|
-
async function refreshCache(actionEndpoint, config, endpointData, grpcOptions, credentials) {
|
|
174
|
-
const cacheStatus = _.get(reflectionCacheStatusMap, [config.protoKey, actionEndpoint]);
|
|
175
|
-
if (!cacheStatus) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
_.set(reflectionCacheStatusMap, [config.protoKey, actionEndpoint], Object.assign(Object.assign({}, cacheStatus), { isRefresh: true }));
|
|
179
|
-
try {
|
|
180
|
-
const res = await getServiceInstanceReflect(config, endpointData, grpcOptions, credentials, true);
|
|
181
|
-
_.set(reflectionServiceInstancesMap, [config.protoKey, actionEndpoint], Promise.resolve(res));
|
|
182
|
-
_.set(reflectionCacheStatusMap, [config.protoKey, actionEndpoint], {
|
|
183
|
-
time: Date.now() / 1000,
|
|
184
|
-
isRefresh: false,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
catch (e) {
|
|
188
|
-
_.set(reflectionCacheStatusMap, [config.protoKey, actionEndpoint], Object.assign(Object.assign({}, cacheStatus), { isRefresh: false }));
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
function getServiceInstanceReflectCached(config, endpointData, grpcOptions, credentials) {
|
|
192
|
-
if (config.reflection === GrpcReflection.OnEveryRequest) {
|
|
193
|
-
return getServiceInstanceReflect(config, endpointData, grpcOptions, credentials);
|
|
194
|
-
}
|
|
195
|
-
const actionEndpoint = createActionEndpoint(endpointData);
|
|
196
|
-
const cacheKey = [config.protoKey, actionEndpoint];
|
|
197
|
-
const cachedServiceInstance = _.get(reflectionServiceInstancesMap, cacheKey);
|
|
198
|
-
if (cachedServiceInstance) {
|
|
199
|
-
if (config.reflectionRefreshSec &&
|
|
200
|
-
needRefreshCache(actionEndpoint, config.protoKey, config.reflectionRefreshSec)) {
|
|
201
|
-
refreshCache(actionEndpoint, config, endpointData, grpcOptions, credentials);
|
|
202
|
-
}
|
|
203
|
-
return cachedServiceInstance;
|
|
204
|
-
}
|
|
205
|
-
const service = getServiceInstanceReflect(config, endpointData, grpcOptions, credentials);
|
|
206
|
-
_.set(reflectionServiceInstancesMap, cacheKey, service);
|
|
207
|
-
service.catch(() => {
|
|
208
|
-
_.set(reflectionServiceInstancesMap, cacheKey, undefined);
|
|
209
|
-
});
|
|
210
|
-
return service;
|
|
211
|
-
}
|
|
212
|
-
async function getServiceInstanceReflect(config, endpointData, grpcOptions, credentials, isRefreshCache) {
|
|
213
|
-
const actionEndpoint = createActionEndpoint(endpointData);
|
|
214
|
-
const endpointInsecure = isExtendedGrpcActionEndpoint(endpointData)
|
|
215
|
-
? endpointData === null || endpointData === void 0 ? void 0 : endpointData.insecure
|
|
216
|
-
: undefined;
|
|
217
|
-
const isInsecure = config.insecure || endpointInsecure;
|
|
218
|
-
const creds = isInsecure ? credentials.insecure : credentials.secure;
|
|
219
|
-
const endpointGrpcOptions = isExtendedGrpcActionEndpoint(endpointData)
|
|
220
|
-
? endpointData.grpcOptions || {}
|
|
221
|
-
: {};
|
|
222
|
-
const combinedGrpcOptions = Object.assign(Object.assign(Object.assign({}, DEFAULT_GRPC_OPTIONS), grpcOptions), endpointGrpcOptions);
|
|
223
|
-
let loadedRoot;
|
|
224
|
-
if (config.reflection === GrpcReflection.OnEveryRequest || isRefreshCache) {
|
|
225
|
-
loadedRoot = await getReflectionRoot(actionEndpoint, config.protoKey, creds, combinedGrpcOptions, isRefreshCache);
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
loadedRoot = await getCachedReflectionRoot(actionEndpoint, config.protoKey, creds, combinedGrpcOptions);
|
|
229
|
-
}
|
|
230
|
-
const descriptor = loadedRoot.toDescriptor('proto3');
|
|
231
|
-
const definition = protoLoader.loadFileDescriptorSetFromObject(descriptor, DEFAULT_PROTO_LOADER_OPTIONS);
|
|
232
|
-
const packageObject = grpc.loadPackageDefinition(definition);
|
|
233
|
-
const Service = _.get(packageObject, config.protoKey);
|
|
234
|
-
const serviceInstance = new Service(actionEndpoint, creds, combinedGrpcOptions);
|
|
235
|
-
return serviceInstance;
|
|
236
|
-
}
|
|
237
|
-
function loadAndCachePackageObject(root, protoPath) {
|
|
238
|
-
var _a;
|
|
239
|
-
const cachedPackageObject = (_a = packageObjectsMap.get(root)) === null || _a === void 0 ? void 0 : _a[protoPath];
|
|
240
|
-
if (cachedPackageObject) {
|
|
241
|
-
return cachedPackageObject;
|
|
242
|
-
}
|
|
243
|
-
root.loadSync(protoPath);
|
|
244
|
-
const definition = protoLoader.loadSync(protoPath, grpcLoaderOptions);
|
|
245
|
-
const packageObject = grpc.loadPackageDefinition(definition);
|
|
246
|
-
let packageObjectsByRoot = packageObjectsMap.get(root);
|
|
247
|
-
if (!packageObjectsByRoot) {
|
|
248
|
-
packageObjectsByRoot = {};
|
|
249
|
-
packageObjectsMap.set(root, packageObjectsByRoot);
|
|
250
|
-
}
|
|
251
|
-
packageObjectsByRoot[protoPath] = packageObject;
|
|
252
|
-
return packageObject;
|
|
253
|
-
}
|
|
254
|
-
async function getServiceInstance(root, config, endpointData, grpcOptions, credentials) {
|
|
255
|
-
if ('reflection' in config) {
|
|
256
|
-
return getServiceInstanceReflectCached(config, endpointData, grpcOptions, credentials);
|
|
257
|
-
}
|
|
258
|
-
const actionEndpoint = createActionEndpoint(endpointData);
|
|
259
|
-
const cacheKey = [config.protoKey, actionEndpoint];
|
|
260
|
-
let serviceInstance = _.get(serviceInstancesMap, cacheKey);
|
|
261
|
-
if (!serviceInstance) {
|
|
262
|
-
const packageObject = loadAndCachePackageObject(root, config.protoPath);
|
|
263
|
-
const Service = _.get(packageObject, config.protoKey);
|
|
264
|
-
const creds = getChannelCredential(config, endpointData, credentials);
|
|
265
|
-
const endpointGrpcOptions = isExtendedGrpcActionEndpoint(endpointData)
|
|
266
|
-
? endpointData.grpcOptions || {}
|
|
267
|
-
: {};
|
|
268
|
-
serviceInstance = new Service(actionEndpoint, creds, Object.assign(Object.assign(Object.assign({}, DEFAULT_GRPC_OPTIONS), grpcOptions), endpointGrpcOptions));
|
|
269
|
-
// Save pointer to service in cache
|
|
270
|
-
_.set(serviceInstancesMap, cacheKey, serviceInstance);
|
|
271
|
-
}
|
|
272
|
-
return serviceInstance;
|
|
273
|
-
}
|
|
274
|
-
async function getResponseData({ config, response, ctx, packageRoot, args, ErrorConstructor, decodeAnyMessageProtoLoaderOptions, }) {
|
|
275
|
-
// Handle operation's runtime protocol buffers
|
|
276
|
-
if (response) {
|
|
277
|
-
const encodedFields = config.encodedFields;
|
|
278
|
-
if (Array.isArray(response)) {
|
|
279
|
-
response.forEach((responseItem) => decodeResponse(responseItem, packageRoot, ctx, encodedFields, ErrorConstructor, decodeAnyMessageProtoLoaderOptions));
|
|
280
|
-
}
|
|
281
|
-
else if (typeof response === 'object') {
|
|
282
|
-
decodeResponse(response, packageRoot, ctx, encodedFields, ErrorConstructor, decodeAnyMessageProtoLoaderOptions);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
let responseData = response;
|
|
286
|
-
if (config.transformResponseData) {
|
|
287
|
-
try {
|
|
288
|
-
responseData = await config.transformResponseData(response, {
|
|
289
|
-
args,
|
|
290
|
-
ctx,
|
|
291
|
-
});
|
|
292
|
-
ctx.log('Transformed response data');
|
|
293
|
-
}
|
|
294
|
-
catch (error) {
|
|
295
|
-
handleError(ErrorConstructor, error, ctx, 'Transform response data failed');
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return responseData;
|
|
299
|
-
}
|
|
300
|
-
export function createGrpcAction({ root, credentials }, endpoints, config, serviceKey, actionName, options, ErrorConstructor) {
|
|
301
|
-
const serviceName = (options === null || options === void 0 ? void 0 : options.serviceName) || serviceKey;
|
|
302
|
-
let getService;
|
|
303
|
-
let recreateService;
|
|
304
|
-
let getActionEndpoint;
|
|
305
|
-
const grpcOptions = (options === null || options === void 0 ? void 0 : options.grpcOptions) || {};
|
|
306
|
-
if (!('reflection' in config)) {
|
|
307
|
-
loadAndCachePackageObject(root, config.protoPath);
|
|
308
|
-
}
|
|
309
|
-
if (typeof config.endpoint === 'function') {
|
|
310
|
-
// ToDo: memoize services in cache keys depends on args
|
|
311
|
-
getActionEndpoint = (args) => {
|
|
312
|
-
const endpointData = config.endpoint(endpoints, args);
|
|
313
|
-
return createActionEndpoint(endpointData);
|
|
314
|
-
};
|
|
315
|
-
getService = (args) => {
|
|
316
|
-
const endpointData = config.endpoint(endpoints, args);
|
|
317
|
-
// Client will be created on first request because it depends on args
|
|
318
|
-
return getServiceInstance(root, config, endpointData, grpcOptions, credentials);
|
|
319
|
-
};
|
|
320
|
-
recreateService = (service, closeTimeout, ctx, args) => {
|
|
321
|
-
const actionEndpoint = getActionEndpoint(args);
|
|
322
|
-
const serviceInstancesCache = 'reflection' in config ? reflectionServiceInstancesMap : serviceInstancesMap;
|
|
323
|
-
const cachePath = [config.protoKey, actionEndpoint];
|
|
324
|
-
clearInstancesCache(service, serviceInstancesCache, cachePath, closeTimeout, ctx);
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
else if (endpoints) {
|
|
328
|
-
let endpointData = endpoints.grpcEndpoint || endpoints.endpoint;
|
|
329
|
-
if (config.endpoint) {
|
|
330
|
-
endpointData = endpoints[config.endpoint];
|
|
331
|
-
}
|
|
332
|
-
if (endpointData) {
|
|
333
|
-
const actionEndpoint = createActionEndpoint(endpointData);
|
|
334
|
-
if ('reflection' in config &&
|
|
335
|
-
(config.reflection === GrpcReflection.OnEveryRequest ||
|
|
336
|
-
config.reflection === GrpcReflection.OnFirstRequest)) {
|
|
337
|
-
getService = () => getServiceInstanceReflectCached(config, endpointData, grpcOptions, credentials);
|
|
338
|
-
recreateService = (service, closeTimeout, ctx) => {
|
|
339
|
-
const cachePath = [config.protoKey, actionEndpoint];
|
|
340
|
-
clearInstancesCache(service, reflectionServiceInstancesMap, cachePath, closeTimeout, ctx);
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
getService = () => getServiceInstance(root, config, endpointData, grpcOptions, credentials);
|
|
345
|
-
recreateService = (service, closeTimeout, ctx) => {
|
|
346
|
-
const serviceInstancesCache = 'reflection' in config
|
|
347
|
-
? reflectionServiceInstancesMap
|
|
348
|
-
: serviceInstancesMap;
|
|
349
|
-
const cachePath = [config.protoKey, actionEndpoint];
|
|
350
|
-
clearInstancesCache(service, serviceInstancesCache, cachePath, closeTimeout, ctx);
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
getActionEndpoint = () => actionEndpoint;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
return async function action(actionConfig) {
|
|
357
|
-
var _a;
|
|
358
|
-
const { args, requestId, headers, ctx: parentCtx, userId } = actionConfig;
|
|
359
|
-
const { action } = config;
|
|
360
|
-
const lang = headers[DEFAULT_LANG_HEADER] || Lang.Ru; // header might be empty string
|
|
361
|
-
const ctx = parentCtx.create(`Gateway ${serviceName} ${actionName} [grpc]`, {
|
|
362
|
-
tags: {
|
|
363
|
-
action: actionName,
|
|
364
|
-
service: serviceName,
|
|
365
|
-
type: 'grpc',
|
|
366
|
-
},
|
|
367
|
-
});
|
|
368
|
-
const startRequestTime = Date.now();
|
|
369
|
-
const requestData = {
|
|
370
|
-
timestamp: startRequestTime,
|
|
371
|
-
service: serviceName,
|
|
372
|
-
action: actionName,
|
|
373
|
-
requestTime: 0,
|
|
374
|
-
requestId: actionConfig.requestId,
|
|
375
|
-
requestMethod: action,
|
|
376
|
-
requestUrl: config.protoKey,
|
|
377
|
-
traceId: ((_a = ctx.getTraceId) === null || _a === void 0 ? void 0 : _a.call(ctx)) || '',
|
|
378
|
-
userId: userId || '',
|
|
379
|
-
};
|
|
380
|
-
const debugHeaders = {
|
|
381
|
-
'x-api-request-action': action,
|
|
382
|
-
'x-api-request-protokey': config.protoKey,
|
|
383
|
-
'x-api-request-lang': lang,
|
|
384
|
-
'x-request-id': requestId,
|
|
385
|
-
'x-gateway-version': VERSION,
|
|
386
|
-
};
|
|
387
|
-
if ('protoPath' in config) {
|
|
388
|
-
debugHeaders['x-api-request-protopath'] = config.protoPath;
|
|
389
|
-
}
|
|
390
|
-
if (typeof options.proxyDebugHeaders === 'function') {
|
|
391
|
-
Object.assign(debugHeaders, options.proxyDebugHeaders(Object.assign({}, headers), 'grpc'));
|
|
392
|
-
}
|
|
393
|
-
else if (Array.isArray(options.proxyDebugHeaders)) {
|
|
394
|
-
for (const headerName of options.proxyDebugHeaders) {
|
|
395
|
-
if (headers[headerName] !== undefined) {
|
|
396
|
-
debugHeaders[`x-gateway-${headerName}`] = headers[headerName];
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
ctx.log('Initiating request', { debugHeaders: sanitizeDebugHeaders(debugHeaders) });
|
|
401
|
-
const sendStats = (status, data) => {
|
|
402
|
-
if (options === null || options === void 0 ? void 0 : options.sendStats) {
|
|
403
|
-
options.sendStats(Object.assign(Object.assign({}, data), { restStatus: status }), redactSensitiveHeaders(parentCtx, headers), parentCtx, { debugHeaders: sanitizeDebugHeaders(debugHeaders) });
|
|
404
|
-
}
|
|
405
|
-
else {
|
|
406
|
-
ctx.stats(Object.assign(Object.assign({}, requestData), { responseStatus: status }));
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
function processError(grpcError) {
|
|
410
|
-
var _a;
|
|
411
|
-
const restStatus = _.get(grpcError.getGatewayError(), 'status', 500);
|
|
412
|
-
sendStats(restStatus, Object.assign(Object.assign({}, requestData), { responseSize: (_a = grpcError.getRawError()) === null || _a === void 0 ? void 0 : _a.metadata, grpcStatus: grpcError.getGatewayError().code }));
|
|
413
|
-
ctx.logError('Request failed', ErrorConstructor.wrap(grpcError.getAppError(ErrorConstructor)), Object.assign({ serviceName,
|
|
414
|
-
actionName, debugHeaders: sanitizeDebugHeaders(debugHeaders) }, grpcError.getGatewayError()));
|
|
415
|
-
ctx.end();
|
|
416
|
-
}
|
|
417
|
-
let params;
|
|
418
|
-
if (config.params) {
|
|
419
|
-
try {
|
|
420
|
-
params = await config.params(args, headers, { ctx });
|
|
421
|
-
}
|
|
422
|
-
catch (error) {
|
|
423
|
-
handleError(ErrorConstructor, error, ctx, 'Getting config params failed');
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
let service;
|
|
427
|
-
try {
|
|
428
|
-
service = await getService(args);
|
|
429
|
-
}
|
|
430
|
-
catch (error) {
|
|
431
|
-
handleError(ErrorConstructor, error, ctx, 'getService failed');
|
|
432
|
-
throw error;
|
|
433
|
-
}
|
|
434
|
-
// eslint-disable-next-line complexity
|
|
435
|
-
return new Promise((resolve, reject) => {
|
|
436
|
-
var _a, _b, _c, _d;
|
|
437
|
-
let endpointData = (endpoints === null || endpoints === void 0 ? void 0 : endpoints.grpcEndpoint) || (endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpoint);
|
|
438
|
-
if (typeof config.endpoint === 'function') {
|
|
439
|
-
endpointData = config.endpoint(endpoints, args);
|
|
440
|
-
}
|
|
441
|
-
else if (config.endpoint) {
|
|
442
|
-
endpointData = _.get(endpoints, [config.endpoint]);
|
|
443
|
-
}
|
|
444
|
-
if (!endpointData) {
|
|
445
|
-
const errorText = `Gateway config error. Endpoint has been not found in service "${serviceKey}"`;
|
|
446
|
-
throw new GrpcError(errorText, {
|
|
447
|
-
status: 400,
|
|
448
|
-
code: 'ENDPOINT_NOT_FOUND',
|
|
449
|
-
message: errorText,
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
const actionEndpoint = getActionEndpoint(args);
|
|
453
|
-
debugHeaders['x-api-request-endpoint'] = actionEndpoint;
|
|
454
|
-
const validationSchema = config.validationSchema || options.validationSchema;
|
|
455
|
-
const invalidParams = validationSchema ? validateArgs(args, validationSchema) : false;
|
|
456
|
-
if (invalidParams) {
|
|
457
|
-
throw new GrpcError('Invalid params', {
|
|
458
|
-
status: 400,
|
|
459
|
-
code: 'INVALID_PARAMS',
|
|
460
|
-
message: 'Validation failed',
|
|
461
|
-
details: {
|
|
462
|
-
title: 'Invalid params',
|
|
463
|
-
description: invalidParams,
|
|
464
|
-
},
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
const timeout = (_c = (_b = (_a = actionConfig === null || actionConfig === void 0 ? void 0 : actionConfig.timeout) !== null && _a !== void 0 ? _a : config === null || config === void 0 ? void 0 : config.timeout) !== null && _b !== void 0 ? _b : options === null || options === void 0 ? void 0 : options.timeout) !== null && _c !== void 0 ? _c : DEFAULT_TIMEOUT;
|
|
468
|
-
const serviceOptions = {
|
|
469
|
-
deadline: Date.now() + timeout,
|
|
470
|
-
};
|
|
471
|
-
const { body = null } = params !== null && params !== void 0 ? params : { body: args };
|
|
472
|
-
const serviceMetadata = createMetadata({
|
|
473
|
-
options,
|
|
474
|
-
actionConfig,
|
|
475
|
-
config,
|
|
476
|
-
params,
|
|
477
|
-
serviceName,
|
|
478
|
-
ctx,
|
|
479
|
-
});
|
|
480
|
-
if (!service[action]) {
|
|
481
|
-
reject(new GrpcError('Not found action', {
|
|
482
|
-
status: 400,
|
|
483
|
-
code: 'GRPC_ACTION_NOT_FOUND',
|
|
484
|
-
message: `Not found action ${action} in ${serviceKey}`,
|
|
485
|
-
}));
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
switch (config.type) {
|
|
489
|
-
case 'serverStream': {
|
|
490
|
-
ctx.log('Creating serverStream request', {
|
|
491
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
492
|
-
});
|
|
493
|
-
const actionCall = service[action].bind(service);
|
|
494
|
-
const stream = actionCall(body, serviceMetadata, serviceOptions);
|
|
495
|
-
stream.on('error', (error) => {
|
|
496
|
-
ctx.log('ServerStream error', {
|
|
497
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
498
|
-
});
|
|
499
|
-
processError(new GrpcError('ClientReadableStream error', parseGrpcError(error, root, lang, config.decodeAnyMessageProtoLoaderOptions), error));
|
|
500
|
-
});
|
|
501
|
-
stream.on('status', (status) => {
|
|
502
|
-
ctx.log('ServerStream status changed', status);
|
|
503
|
-
});
|
|
504
|
-
stream.on('end', () => {
|
|
505
|
-
ctx.log('ServerStream request completed', {
|
|
506
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
507
|
-
});
|
|
508
|
-
ctx.end();
|
|
509
|
-
});
|
|
510
|
-
resolve({ debugHeaders, stream });
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
case 'clientStream': {
|
|
514
|
-
ctx.log('Creating clientStream request', {
|
|
515
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
516
|
-
});
|
|
517
|
-
if (!actionConfig.callback) {
|
|
518
|
-
throw new GrpcError('Invalid action type', {
|
|
519
|
-
status: 400,
|
|
520
|
-
code: 'ACTION_CALLBACK_REQUIRED',
|
|
521
|
-
message: `Client stream actions require callback function`,
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
const actionCall = service[action].bind(service);
|
|
525
|
-
const stream = actionCall(serviceMetadata, serviceOptions, actionConfig.callback);
|
|
526
|
-
resolve({ debugHeaders, stream });
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
case 'bidi': {
|
|
530
|
-
ctx.log('Creating serverStream request', {
|
|
531
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
532
|
-
});
|
|
533
|
-
const actionCall = service[action].bind(service);
|
|
534
|
-
const stream = actionCall(serviceMetadata, serviceOptions);
|
|
535
|
-
stream.on('error', (error) => {
|
|
536
|
-
ctx.log('BidiStream error', {
|
|
537
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
538
|
-
});
|
|
539
|
-
processError(new GrpcError('BidiStream error', parseGrpcError(error, root, lang, config.decodeAnyMessageProtoLoaderOptions), error));
|
|
540
|
-
});
|
|
541
|
-
stream.on('status', (status) => {
|
|
542
|
-
ctx.log('BidiStream status changed', status);
|
|
543
|
-
});
|
|
544
|
-
stream.on('end', () => {
|
|
545
|
-
ctx.log('BidiStream request completed', {
|
|
546
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
547
|
-
});
|
|
548
|
-
ctx.end();
|
|
549
|
-
});
|
|
550
|
-
resolve({
|
|
551
|
-
debugHeaders,
|
|
552
|
-
stream,
|
|
553
|
-
});
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
default: {
|
|
557
|
-
ctx.log('Starting unary request', {
|
|
558
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
559
|
-
});
|
|
560
|
-
let retries = (_d = config.retries) !== null && _d !== void 0 ? _d : 0;
|
|
561
|
-
let actionCall = service[action].bind(service);
|
|
562
|
-
const callAction = () => {
|
|
563
|
-
let trailingMetadata = {};
|
|
564
|
-
const call = actionCall(body, serviceMetadata, serviceOptions, async (error, response) => {
|
|
565
|
-
const endRequestTime = Date.now();
|
|
566
|
-
requestData.requestTime = endRequestTime - startRequestTime;
|
|
567
|
-
const shouldRecreateService = error &&
|
|
568
|
-
options.grpcRecreateService &&
|
|
569
|
-
isRecreateServiceError(error);
|
|
570
|
-
const shouldRetry = error && retries && isRetryableError(error);
|
|
571
|
-
if (shouldRecreateService) {
|
|
572
|
-
ctx.log(`Service client for ${config.protoKey} is going to be re-created`);
|
|
573
|
-
recreateService(service, timeout * 1.5, ctx, args);
|
|
574
|
-
}
|
|
575
|
-
if (shouldRetry) {
|
|
576
|
-
ctx.logError(`Request failed, retrying ${retries--} more times`);
|
|
577
|
-
// Update pointer to re-created client in local service variable
|
|
578
|
-
try {
|
|
579
|
-
service = await getService(args);
|
|
580
|
-
}
|
|
581
|
-
catch (error) {
|
|
582
|
-
handleError(ErrorConstructor, error, ctx, 'getService failed');
|
|
583
|
-
throw error;
|
|
584
|
-
}
|
|
585
|
-
// Update service
|
|
586
|
-
actionCall = service[action].bind(service);
|
|
587
|
-
callAction();
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
if (error) {
|
|
591
|
-
reject(new GrpcError('gRPC request error', parseGrpcError(error, root, lang, config.decodeAnyMessageProtoLoaderOptions), error));
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
const responseData = await getResponseData({
|
|
595
|
-
response,
|
|
596
|
-
ctx,
|
|
597
|
-
config,
|
|
598
|
-
args,
|
|
599
|
-
packageRoot: root,
|
|
600
|
-
ErrorConstructor,
|
|
601
|
-
decodeAnyMessageProtoLoaderOptions: config.decodeAnyMessageProtoLoaderOptions,
|
|
602
|
-
});
|
|
603
|
-
const responseHeaders = {};
|
|
604
|
-
if (config.proxyResponseHeaders) {
|
|
605
|
-
const proxyResponseHeaders = [];
|
|
606
|
-
const headersFromMetadata = getHeadersFromMetadata(trailingMetadata);
|
|
607
|
-
if (typeof config.proxyResponseHeaders === 'function') {
|
|
608
|
-
Object.assign(responseHeaders, config.proxyResponseHeaders(headersFromMetadata, 'grpc'));
|
|
609
|
-
}
|
|
610
|
-
else if (Array.isArray(config.proxyResponseHeaders)) {
|
|
611
|
-
proxyResponseHeaders.push(...config.proxyResponseHeaders);
|
|
612
|
-
}
|
|
613
|
-
for (const headerName of proxyResponseHeaders) {
|
|
614
|
-
if (responseHeaders[headerName] === undefined) {
|
|
615
|
-
responseHeaders[headerName] =
|
|
616
|
-
headersFromMetadata[headerName];
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
Object.assign(debugHeaders, getHeadersFromMetadata(trailingMetadata, 'x-metadata-'));
|
|
621
|
-
sendStats(200, Object.assign(Object.assign({}, requestData), { responseSize: sizeof(response), grpcStatus: 0 }));
|
|
622
|
-
ctx.log('Request completed', {
|
|
623
|
-
debugHeaders: sanitizeDebugHeaders(debugHeaders),
|
|
624
|
-
});
|
|
625
|
-
ctx.end();
|
|
626
|
-
return resolve({ responseData, responseHeaders, debugHeaders });
|
|
627
|
-
});
|
|
628
|
-
call.on('status', (status) => {
|
|
629
|
-
trailingMetadata = status.metadata.toJSON();
|
|
630
|
-
});
|
|
631
|
-
};
|
|
632
|
-
callAction();
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}).catch((error) => {
|
|
636
|
-
const grpcError = isGrpcError(error) ? error : grpcErrorFactory(error);
|
|
637
|
-
processError(grpcError);
|
|
638
|
-
return Promise.reject({ error: grpcError.getGatewayError(), debugHeaders });
|
|
639
|
-
});
|
|
640
|
-
};
|
|
641
|
-
}
|