@gravity-ui/gateway 4.7.2 → 4.9.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/README.md +38 -4
- package/build/components/grpc.d.ts +3 -3
- package/build/components/grpc.js +40 -6
- package/build/components/rest.d.ts +2 -2
- package/build/components/rest.js +7 -7
- package/build/index.js +8 -5
- package/build/models/common.d.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ A flexible and powerful Express controller for working with REST and gRPC APIs i
|
|
|
7
7
|
- [Installation](#installation)
|
|
8
8
|
- [Basic Usage](#basic-usage)
|
|
9
9
|
- [Configuration](#configuration)
|
|
10
|
+
- [`proxyHeaders`](#proxyheaders)
|
|
10
11
|
- [Validation Schema](#validation-schema)
|
|
11
12
|
- [Using the API in Node.js](#using-the-api-in-nodejs)
|
|
12
13
|
- [Schema Scopes](#schema-scopes)
|
|
@@ -14,13 +15,16 @@ A flexible and powerful Express controller for working with REST and gRPC APIs i
|
|
|
14
15
|
- [Overriding Endpoints](#overriding-endpoints)
|
|
15
16
|
- [Authentication](#authentication)
|
|
16
17
|
- [Error Handling](#error-handling)
|
|
17
|
-
- [gRPC Reflection](#grpc-reflection-for-grpc-actions)
|
|
18
18
|
- [Retryable Errors](#retryable-errors)
|
|
19
|
+
- [REST-actions](#rest-actions)
|
|
20
|
+
- [gRPC-actions](#grpc-actions)
|
|
19
21
|
- [Request Cancellation](#request-cancellation)
|
|
20
22
|
- [Response Content Type Validation](#response-content-type-validation)
|
|
23
|
+
- [gRPC Reflection for gRPC Actions](#grpc-reflection-for-grpc-actions)
|
|
21
24
|
- [Development](#development)
|
|
22
25
|
- [Running Tests](#running-tests)
|
|
23
26
|
- [Contributing](#contributing)
|
|
27
|
+
- [License](#license)
|
|
24
28
|
|
|
25
29
|
## Installation
|
|
26
30
|
|
|
@@ -173,10 +177,13 @@ interface GatewayConfig {
|
|
|
173
177
|
// List of paths to the necessary proto files for the gateway.
|
|
174
178
|
includeProtoRoots?: string[];
|
|
175
179
|
|
|
176
|
-
// Configuration of the path to the certificate in gRPC.
|
|
180
|
+
// Configuration of the path to the CA certificate in gRPC.
|
|
177
181
|
// Set to null to use system certificates by default.
|
|
178
182
|
caCertificatePath?: string | null;
|
|
179
|
-
|
|
183
|
+
// Configuration of the path to the client certificate for mTLS in gRPC.
|
|
184
|
+
clientCertificatePath?: string | null;
|
|
185
|
+
// Configuration of the path to the client private key for mTLS in gRPC.
|
|
186
|
+
clientKeyPath?: string | null;
|
|
180
187
|
// Telemetry sending configuration.
|
|
181
188
|
sendStats?: SendStats;
|
|
182
189
|
|
|
@@ -312,6 +319,9 @@ const config = {
|
|
|
312
319
|
includeProtoRoots: ['...'],
|
|
313
320
|
timeout: 25000, // default 25 seconds
|
|
314
321
|
caCertificatePath: '...',
|
|
322
|
+
// Optional: paths for mTLS client certificate and key
|
|
323
|
+
clientCertificatePath: '...',
|
|
324
|
+
clientKeyPath: '...',
|
|
315
325
|
};
|
|
316
326
|
|
|
317
327
|
const {api: gatewayApi} = getGatewayControllers({root: Schema}, config);
|
|
@@ -455,17 +465,41 @@ const config = {
|
|
|
455
465
|
};
|
|
456
466
|
```
|
|
457
467
|
|
|
458
|
-
You can
|
|
468
|
+
You can define authentication at three levels:
|
|
469
|
+
|
|
|
470
|
+
|
|
471
|
+
1. **Gateway level** (global) - as shown above
|
|
472
|
+
2. **Service level** - by adding authentication methods to the service definition
|
|
473
|
+
3. **Action level** (most specific) - by adding authentication methods to individual actions
|
|
474
|
+
|
|
|
475
|
+
The authentication methods are checked in the following order: action > service > gateway.
|
|
476
|
+
|
|
|
477
|
+
**Service-level authentication:**
|
|
478
|
+
|
|
|
459
479
|
|
|
460
480
|
```javascript
|
|
461
481
|
const schema = {
|
|
462
482
|
userService: {
|
|
463
483
|
serviceName: 'users',
|
|
464
484
|
endpoints: {...},
|
|
485
|
+
// Service-level authentication
|
|
486
|
+
getAuthHeaders: (params) => ({
|
|
487
|
+
'X-User-Service-Auth': params.token,
|
|
488
|
+
}),
|
|
489
|
+
getAuthArgs: (req, res) => ({
|
|
490
|
+
token: req.authorization.token,
|
|
491
|
+
serviceSpecificData: req.headers['x-service-data'],
|
|
492
|
+
}),
|
|
465
493
|
actions: {
|
|
466
494
|
getProfile: {
|
|
467
495
|
path: () => '/profile',
|
|
468
496
|
method: 'GET',
|
|
497
|
+
// Uses service-level authentication
|
|
498
|
+
},
|
|
499
|
+
updateProfile: {
|
|
500
|
+
path: () => '/profile',
|
|
501
|
+
method: 'PUT',
|
|
502
|
+
// Action-level authentication (overrides service-level)
|
|
469
503
|
getAuthHeaders: (params) => ({
|
|
470
504
|
'X-Special-Auth': params.token,
|
|
471
505
|
}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as grpc from '@grpc/grpc-js';
|
|
2
2
|
import * as protobufjs from 'protobufjs';
|
|
3
3
|
import type * as descriptor from 'protobufjs/ext/descriptor';
|
|
4
|
-
import { ApiActionConfig, ApiServiceGrpcActionConfig, EndpointsConfig, GatewayApiOptions } from '../models/common';
|
|
4
|
+
import { ApiActionConfig, ApiServiceGrpcActionConfig, BaseSchema, EndpointsConfig, GatewayApiOptions } from '../models/common';
|
|
5
5
|
import { GatewayContext } from '../models/context';
|
|
6
6
|
import { AppErrorConstructor } from '../models/error';
|
|
7
7
|
declare module 'protobufjs' {
|
|
@@ -19,6 +19,6 @@ export interface GrpcContext {
|
|
|
19
19
|
credentials: CredentialsMap;
|
|
20
20
|
}
|
|
21
21
|
export declare function createRoot(includeGrpcPaths?: string[]): protobufjs.Root;
|
|
22
|
-
export declare function getCredentialsMap(caCertificatePath?: string | null): CredentialsMap;
|
|
23
|
-
export default 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").GatewayActionClientStreamResponse<any> | import("../models/common").GatewayActionServerStreamResponse<any> | import("../models/common").GatewayActionDuplexStreamResponse<any> | import("../models/common").GatewayActionUnaryResponse<any>>;
|
|
22
|
+
export declare function getCredentialsMap(caCertificatePath?: string | null, clientCertificatePath?: string | null, clientKeyPath?: string | null): CredentialsMap;
|
|
23
|
+
export default 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, serviceSchema?: Pick<BaseSchema[string], 'getAuthHeaders'>): (actionConfig: ApiActionConfig<Context, any, any>) => Promise<import("../models/common").GatewayActionClientStreamResponse<any> | import("../models/common").GatewayActionServerStreamResponse<any> | import("../models/common").GatewayActionDuplexStreamResponse<any> | import("../models/common").GatewayActionUnaryResponse<any>>;
|
|
24
24
|
export {};
|
package/build/components/grpc.js
CHANGED
|
@@ -59,13 +59,21 @@ function createRoot(includeGrpcPaths) {
|
|
|
59
59
|
return root;
|
|
60
60
|
}
|
|
61
61
|
exports.createRoot = createRoot;
|
|
62
|
-
function getCredentialsMap(caCertificatePath) {
|
|
62
|
+
function getCredentialsMap(caCertificatePath, clientCertificatePath, clientKeyPath) {
|
|
63
63
|
let certificate;
|
|
64
|
+
let clientCertificate;
|
|
65
|
+
let clientKey;
|
|
64
66
|
if (caCertificatePath && fs_1.default.existsSync(caCertificatePath)) {
|
|
65
67
|
certificate = fs_1.default.readFileSync(caCertificatePath);
|
|
66
68
|
}
|
|
69
|
+
if (clientCertificatePath && fs_1.default.existsSync(clientCertificatePath)) {
|
|
70
|
+
clientCertificate = fs_1.default.readFileSync(clientCertificatePath);
|
|
71
|
+
}
|
|
72
|
+
if (clientKeyPath && fs_1.default.existsSync(clientKeyPath)) {
|
|
73
|
+
clientKey = fs_1.default.readFileSync(clientKeyPath);
|
|
74
|
+
}
|
|
67
75
|
return {
|
|
68
|
-
secure: grpc.ChannelCredentials.createSsl(certificate),
|
|
76
|
+
secure: grpc.ChannelCredentials.createSsl(certificate, clientKey, clientCertificate),
|
|
69
77
|
secureWithoutRootCert: grpc.ChannelCredentials.createSsl(),
|
|
70
78
|
insecure: grpc.ChannelCredentials.createInsecure(),
|
|
71
79
|
};
|
|
@@ -86,8 +94,8 @@ function decodeResponse(response, packageRoot, ctx, encodedFields = [], ErrorCon
|
|
|
86
94
|
}
|
|
87
95
|
});
|
|
88
96
|
}
|
|
89
|
-
function createMetadata({ options, actionConfig, config, params, serviceName, proxyHeadersCaller, ctx, }) {
|
|
90
|
-
var _a;
|
|
97
|
+
function createMetadata({ options, actionConfig, config, params, serviceName, proxyHeadersCaller, ctx, serviceSchema, }) {
|
|
98
|
+
var _a, _b;
|
|
91
99
|
const { headers, requestId, authArgs } = actionConfig;
|
|
92
100
|
const proxyHeaders = [...constants_1.DEFAULT_PROXY_HEADERS];
|
|
93
101
|
let metadata = {
|
|
@@ -111,7 +119,7 @@ function createMetadata({ options, actionConfig, config, params, serviceName, pr
|
|
|
111
119
|
metadata[headerName] = headers[headerName];
|
|
112
120
|
}
|
|
113
121
|
}
|
|
114
|
-
const authHeaders = ((_a = config.getAuthHeaders) !== null && _a !== void 0 ? _a : options.getAuthHeaders)({
|
|
122
|
+
const authHeaders = ((_b = (_a = config.getAuthHeaders) !== null && _a !== void 0 ? _a : serviceSchema === null || serviceSchema === void 0 ? void 0 : serviceSchema.getAuthHeaders) !== null && _b !== void 0 ? _b : options.getAuthHeaders)({
|
|
115
123
|
actionType: 'grpc',
|
|
116
124
|
serviceName,
|
|
117
125
|
requestHeaders: headers,
|
|
@@ -170,12 +178,37 @@ function clearInstancesCache(service, instancesMap, cachePath, closeTimeout, ctx
|
|
|
170
178
|
function getChannelCredential(config, endpointData, credentials) {
|
|
171
179
|
let endpointInsecure;
|
|
172
180
|
let endpointSecureWithoutRootCert;
|
|
181
|
+
let endpointCaCertificatePath;
|
|
182
|
+
let endpointClientCertificatePath;
|
|
183
|
+
let endpointClientKeyPath;
|
|
173
184
|
if ((0, common_2.isExtendedGrpcActionEndpoint)(endpointData)) {
|
|
174
185
|
endpointInsecure = endpointData === null || endpointData === void 0 ? void 0 : endpointData.insecure;
|
|
175
186
|
endpointSecureWithoutRootCert = endpointData === null || endpointData === void 0 ? void 0 : endpointData.secureWithoutRootCert;
|
|
187
|
+
endpointCaCertificatePath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.caCertificatePath;
|
|
188
|
+
endpointClientCertificatePath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.clientCertificatePath;
|
|
189
|
+
endpointClientKeyPath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.clientKeyPath;
|
|
176
190
|
}
|
|
177
191
|
const isInsecure = config.insecure || endpointInsecure;
|
|
178
192
|
const isSecureWithoutRootCert = config.secureWithoutRootCert || endpointSecureWithoutRootCert;
|
|
193
|
+
// If endpoint-specific certificates are provided, create new credentials
|
|
194
|
+
if (endpointCaCertificatePath || endpointClientCertificatePath || endpointClientKeyPath) {
|
|
195
|
+
let certificate;
|
|
196
|
+
let clientCertificate;
|
|
197
|
+
let clientKey;
|
|
198
|
+
const caCertPath = endpointCaCertificatePath || config.caCertificatePath;
|
|
199
|
+
const clientCertPath = endpointClientCertificatePath || config.clientCertificatePath;
|
|
200
|
+
const clientKeyPath = endpointClientKeyPath || config.clientKeyPath;
|
|
201
|
+
if (caCertPath && fs_1.default.existsSync(caCertPath)) {
|
|
202
|
+
certificate = fs_1.default.readFileSync(caCertPath);
|
|
203
|
+
}
|
|
204
|
+
if (clientCertPath && fs_1.default.existsSync(clientCertPath)) {
|
|
205
|
+
clientCertificate = fs_1.default.readFileSync(clientCertPath);
|
|
206
|
+
}
|
|
207
|
+
if (clientKeyPath && fs_1.default.existsSync(clientKeyPath)) {
|
|
208
|
+
clientKey = fs_1.default.readFileSync(clientKeyPath);
|
|
209
|
+
}
|
|
210
|
+
return grpc.ChannelCredentials.createSsl(certificate, clientKey, clientCertificate);
|
|
211
|
+
}
|
|
179
212
|
let creds = credentials.secure;
|
|
180
213
|
if (isInsecure) {
|
|
181
214
|
creds = credentials.insecure;
|
|
@@ -333,7 +366,7 @@ function createServiceOptions(timeout) {
|
|
|
333
366
|
deadline: Date.now() + timeout,
|
|
334
367
|
};
|
|
335
368
|
}
|
|
336
|
-
function createGrpcAction({ root, credentials }, endpoints, config, serviceKey, actionName, options, ErrorConstructor) {
|
|
369
|
+
function createGrpcAction({ root, credentials }, endpoints, config, serviceKey, actionName, options, ErrorConstructor, serviceSchema) {
|
|
337
370
|
const serviceName = (options === null || options === void 0 ? void 0 : options.serviceName) || serviceKey;
|
|
338
371
|
let getService;
|
|
339
372
|
let recreateService;
|
|
@@ -520,6 +553,7 @@ function createGrpcAction({ root, credentials }, endpoints, config, serviceKey,
|
|
|
520
553
|
serviceName,
|
|
521
554
|
proxyHeadersCaller,
|
|
522
555
|
ctx,
|
|
556
|
+
serviceSchema,
|
|
523
557
|
});
|
|
524
558
|
if (!service[action]) {
|
|
525
559
|
reject(new parse_error_1.GrpcError('Not found action', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ApiActionConfig, ApiServiceRestActionConfig, EndpointsConfig, GatewayApiOptions, Headers } from '../models/common';
|
|
1
|
+
import { ApiActionConfig, ApiServiceRestActionConfig, BaseSchema, EndpointsConfig, GatewayApiOptions, Headers } from '../models/common';
|
|
2
2
|
import { GatewayContext } from '../models/context';
|
|
3
3
|
import { AppErrorConstructor } from '../models/error';
|
|
4
|
-
export default function createRestAction<Context extends GatewayContext>(endpoints: EndpointsConfig | undefined, config: ApiServiceRestActionConfig<Context, any, any>, serviceKey: string, actionName: string, options: GatewayApiOptions<Context>, ErrorConstructor: AppErrorConstructor): (actionConfig: ApiActionConfig<Context, any>) => Promise<{
|
|
4
|
+
export default function createRestAction<Context extends GatewayContext>(endpoints: EndpointsConfig | undefined, config: ApiServiceRestActionConfig<Context, any, any>, serviceKey: string, actionName: string, options: GatewayApiOptions<Context>, ErrorConstructor: AppErrorConstructor, serviceSchema?: Pick<BaseSchema[string], 'getAuthHeaders'>): (actionConfig: ApiActionConfig<Context, any>) => Promise<{
|
|
5
5
|
responseData: unknown;
|
|
6
6
|
responseHeaders?: Headers | undefined;
|
|
7
7
|
debugHeaders: Headers;
|
package/build/components/rest.js
CHANGED
|
@@ -33,13 +33,13 @@ function getConfigSerializerFunction(config) {
|
|
|
33
33
|
}
|
|
34
34
|
return undefined;
|
|
35
35
|
}
|
|
36
|
-
function createRestAction(endpoints, config, serviceKey, actionName, options, ErrorConstructor) {
|
|
36
|
+
function createRestAction(endpoints, config, serviceKey, actionName, options, ErrorConstructor, serviceSchema) {
|
|
37
37
|
var _a, _b, _c, _d;
|
|
38
38
|
const timeout = (_c = (_a = config === null || config === void 0 ? void 0 : config.timeout) !== null && _a !== void 0 ? _a : (_b = options === null || options === void 0 ? void 0 : options.axiosConfig) === null || _b === void 0 ? void 0 : _b.timeout) !== null && _c !== void 0 ? _c : options === null || options === void 0 ? void 0 : options.timeout;
|
|
39
39
|
const defaultAxiosClient = (0, axios_1.getAxiosClient)(timeout, config === null || config === void 0 ? void 0 : config.retries, (_d = config === null || config === void 0 ? void 0 : config.axiosRetryCondition) !== null && _d !== void 0 ? _d : options === null || options === void 0 ? void 0 : options.axiosRetryCondition, options === null || options === void 0 ? void 0 : options.axiosConfig, options === null || options === void 0 ? void 0 : options.axiosInterceptors);
|
|
40
40
|
/* eslint-disable complexity */
|
|
41
41
|
return async function action(actionConfig) {
|
|
42
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
43
43
|
const { args, requestId, headers: requestHeaders, ctx: parentCtx, authArgs, userId, abortSignal, } = actionConfig;
|
|
44
44
|
const debugHeaders = {};
|
|
45
45
|
const lang = requestHeaders[constants_1.DEFAULT_LANG_HEADER] || constants_1.Lang.Ru; // header might be empty string
|
|
@@ -142,7 +142,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
142
142
|
if (idempotency) {
|
|
143
143
|
actionHeaders['idempotency-key'] = requestHeaders['idempotency-key'] || (0, uuid_1.v4)();
|
|
144
144
|
}
|
|
145
|
-
const authHeaders = ((_b = config.getAuthHeaders) !== null && _b !== void 0 ? _b : options.getAuthHeaders)({
|
|
145
|
+
const authHeaders = ((_c = (_b = config.getAuthHeaders) !== null && _b !== void 0 ? _b : serviceSchema === null || serviceSchema === void 0 ? void 0 : serviceSchema.getAuthHeaders) !== null && _c !== void 0 ? _c : options.getAuthHeaders)({
|
|
146
146
|
actionType: 'rest',
|
|
147
147
|
serviceName,
|
|
148
148
|
requestHeaders,
|
|
@@ -202,7 +202,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
202
202
|
}
|
|
203
203
|
const startRequestTime = Date.now();
|
|
204
204
|
let axiosClient = defaultAxiosClient;
|
|
205
|
-
const customActionTimeout = (
|
|
205
|
+
const customActionTimeout = (_f = (_e = (_d = actionConfig.timeout) !== null && _d !== void 0 ? _d : config.timeout) !== null && _e !== void 0 ? _e : endpointAxiosConfig === null || endpointAxiosConfig === void 0 ? void 0 : endpointAxiosConfig.timeout) !== null && _f !== void 0 ? _f : timeout;
|
|
206
206
|
if (actionConfig.timeout || endpointAxiosConfig) {
|
|
207
207
|
const customActionAxiosConfig = Object.assign(Object.assign({}, ((options === null || options === void 0 ? void 0 : options.axiosConfig) || {})), (endpointAxiosConfig || {}));
|
|
208
208
|
axiosClient = (0, axios_1.getAxiosClient)(customActionTimeout, config === null || config === void 0 ? void 0 : config.retries, options.axiosRetryCondition, customActionAxiosConfig, options === null || options === void 0 ? void 0 : options.axiosInterceptors);
|
|
@@ -216,7 +216,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
216
216
|
requestId,
|
|
217
217
|
requestMethod: config.method,
|
|
218
218
|
requestUrl: actionURL,
|
|
219
|
-
traceId: ((
|
|
219
|
+
traceId: ((_g = ctx.getTraceId) === null || _g === void 0 ? void 0 : _g.call(ctx)) || '',
|
|
220
220
|
userId: userId || '',
|
|
221
221
|
};
|
|
222
222
|
const requestConfig = {
|
|
@@ -243,7 +243,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
243
243
|
const responseHeaders = {};
|
|
244
244
|
const endRequestTime = Date.now();
|
|
245
245
|
requestData.requestTime = endRequestTime - startRequestTime;
|
|
246
|
-
const actualResponseContentType = (
|
|
246
|
+
const actualResponseContentType = (_h = response.headers) === null || _h === void 0 ? void 0 : _h['Content-Type'];
|
|
247
247
|
const expectedResponseContentType = config.expectedResponseContentType || options.expectedResponseContentType;
|
|
248
248
|
if (actualResponseContentType && expectedResponseContentType) {
|
|
249
249
|
let isInvalidResponseContentType;
|
|
@@ -340,7 +340,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
340
340
|
}
|
|
341
341
|
const responseStatus = lodash_1.default.get(parsedError, 'status') || lodash_1.default.get(error, 'status', 500);
|
|
342
342
|
if (options === null || options === void 0 ? void 0 : options.sendStats) {
|
|
343
|
-
options.sendStats(Object.assign(Object.assign({}, requestData), { responseSize: getRestResponseSize((
|
|
343
|
+
options.sendStats(Object.assign(Object.assign({}, requestData), { responseSize: getRestResponseSize((_j = error === null || error === void 0 ? void 0 : error.response) === null || _j === void 0 ? void 0 : _j.data, ctx, ErrorConstructor), restStatus: responseStatus, userId }), (0, redact_sensitive_headers_1.redactSensitiveHeaders)(parentCtx, headers), parentCtx, { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
|
|
344
344
|
}
|
|
345
345
|
else {
|
|
346
346
|
ctx.stats(Object.assign(Object.assign({}, requestData), { responseStatus }));
|
package/build/index.js
CHANGED
|
@@ -85,7 +85,7 @@ function createApiAction(schema, config, serviceKey, actionName, api, grpcContex
|
|
|
85
85
|
validationSchema: config.validationSchema,
|
|
86
86
|
encodePathArgs: config.encodePathArgs,
|
|
87
87
|
getAuthHeaders: config.getAuthHeaders,
|
|
88
|
-
}, config.ErrorConstructor);
|
|
88
|
+
}, config.ErrorConstructor, serviceSchema);
|
|
89
89
|
}
|
|
90
90
|
const grpcRecreateService = (_a = config.grpcRecreateService) !== null && _a !== void 0 ? _a : true;
|
|
91
91
|
return (0, grpc_1.default)(grpcContext, endpointsConfig, action, serviceKey, actionName, {
|
|
@@ -98,7 +98,7 @@ function createApiAction(schema, config, serviceKey, actionName, api, grpcContex
|
|
|
98
98
|
grpcOptions: config.grpcOptions,
|
|
99
99
|
grpcRecreateService,
|
|
100
100
|
getAuthHeaders: config.getAuthHeaders,
|
|
101
|
-
}, config.ErrorConstructor);
|
|
101
|
+
}, config.ErrorConstructor, serviceSchema);
|
|
102
102
|
}
|
|
103
103
|
function generateGatewayApi(schema, config, grpcContext, baseApi) {
|
|
104
104
|
const { installation, env } = config;
|
|
@@ -117,7 +117,7 @@ function generateGatewayApi(schema, config, grpcContext, baseApi) {
|
|
|
117
117
|
function generateGatewayApiController(schemasByScope, Api, config, controllerActions) {
|
|
118
118
|
// eslint-disable-next-line complexity
|
|
119
119
|
return async function gateway(req, res) {
|
|
120
|
-
var _a, _b, _c;
|
|
120
|
+
var _a, _b, _c, _d;
|
|
121
121
|
const { userId } = res.locals || {};
|
|
122
122
|
const { service, action, scope = 'root' } = req.params;
|
|
123
123
|
const withDebugHeaders = typeof config.withDebugHeaders === 'function'
|
|
@@ -192,12 +192,15 @@ function generateGatewayApiController(schemasByScope, Api, config, controllerAct
|
|
|
192
192
|
throw { error, debugHeaders: {} };
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
+
const serviceSchema = (_d = schemasByScope[scope]) === null || _d === void 0 ? void 0 : _d[service];
|
|
195
196
|
const { responseData, responseHeaders, debugHeaders } = await apiAction({
|
|
196
197
|
requestId: req.id,
|
|
197
198
|
headers: req.headers,
|
|
198
199
|
ctx: req.ctx,
|
|
199
200
|
args,
|
|
200
|
-
authArgs:
|
|
201
|
+
authArgs: (serviceSchema === null || serviceSchema === void 0 ? void 0 : serviceSchema.getAuthArgs)
|
|
202
|
+
? serviceSchema.getAuthArgs(req, res)
|
|
203
|
+
: config.getAuthArgs(req, res),
|
|
201
204
|
userId,
|
|
202
205
|
abortSignal: abortController.signal,
|
|
203
206
|
});
|
|
@@ -256,7 +259,7 @@ function getGatewayControllers(schemasByScope, config) {
|
|
|
256
259
|
console.warn('Error when parse GATEWAY_ENDPOINTS_OVERRIDES', err);
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
|
-
const credentials = (0, grpc_1.getCredentialsMap)(config.caCertificatePath);
|
|
262
|
+
const credentials = (0, grpc_1.getCredentialsMap)(config.caCertificatePath, config.clientCertificatePath, config.clientKeyPath);
|
|
260
263
|
for (const scope of (0, common_1.getKeys)(schemasByScope)) {
|
|
261
264
|
apiByScope[scope] = generateGatewayApi(schemasByScope[scope], config, { root: (0, grpc_1.createRoot)(config.includeProtoRoots), credentials }, apiByScope);
|
|
262
265
|
}
|
package/build/models/common.d.ts
CHANGED
|
@@ -118,6 +118,9 @@ export interface ExtendedBaseActionEndpoint {
|
|
|
118
118
|
export interface ExtendedGrpcActionEndpoint extends ExtendedBaseActionEndpoint {
|
|
119
119
|
insecure?: boolean;
|
|
120
120
|
secureWithoutRootCert?: boolean;
|
|
121
|
+
caCertificatePath?: string;
|
|
122
|
+
clientCertificatePath?: string;
|
|
123
|
+
clientKeyPath?: string;
|
|
121
124
|
grpcOptions?: object;
|
|
122
125
|
}
|
|
123
126
|
export interface ExtendedRestActionEndpoint extends ExtendedBaseActionEndpoint {
|
|
@@ -154,6 +157,9 @@ export interface ApiServiceBaseGrpcActionConfig<Context extends GatewayContext,
|
|
|
154
157
|
protoKey: string;
|
|
155
158
|
insecure?: boolean;
|
|
156
159
|
secureWithoutRootCert?: boolean;
|
|
160
|
+
caCertificatePath?: string;
|
|
161
|
+
clientCertificatePath?: string;
|
|
162
|
+
clientKeyPath?: string;
|
|
157
163
|
encodedFields?: string[];
|
|
158
164
|
type?: HandlerType;
|
|
159
165
|
decodeAnyMessageProtoLoaderOptions?: protobufjs.IConversionOptions;
|
|
@@ -199,6 +205,8 @@ export interface BaseSchema {
|
|
|
199
205
|
actions: Record<string, ApiServiceActionConfig<any, any, any, any, any, any>>;
|
|
200
206
|
serviceName?: string;
|
|
201
207
|
endpoints?: Record<string, Record<string, EndpointsConfig>>;
|
|
208
|
+
getAuthHeaders?: GetAuthHeaders;
|
|
209
|
+
getAuthArgs?: (req: Request, res: Response) => Record<string, unknown> | undefined;
|
|
202
210
|
};
|
|
203
211
|
}
|
|
204
212
|
export interface SchemasByScope {
|
|
@@ -272,6 +280,8 @@ export interface GatewayConfig<Context extends GatewayContext, Req extends Gatew
|
|
|
272
280
|
sendStats?: SendStats<Context>;
|
|
273
281
|
includeProtoRoots?: string[];
|
|
274
282
|
caCertificatePath: string | null;
|
|
283
|
+
clientCertificatePath?: string | null;
|
|
284
|
+
clientKeyPath?: string | null;
|
|
275
285
|
proxyHeaders: ProxyHeaders;
|
|
276
286
|
proxyDebugHeaders?: ProxyHeaders;
|
|
277
287
|
withDebugHeaders?: boolean | ((req: Req, res: Res) => boolean);
|