@gravity-ui/gateway 4.8.0 → 4.10.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 +15 -3
- package/build/components/grpc.d.ts +1 -1
- package/build/components/grpc.js +39 -3
- package/build/components/rest.js +4 -1
- package/build/index.js +1 -1
- package/build/models/common.d.ts +8 -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
|
|
|
@@ -250,6 +257,8 @@ The `extra` parameter contains additional information about the request:
|
|
|
250
257
|
- `protopath`: The proto path (for gRPC actions)
|
|
251
258
|
- `protokey`: The proto key (for gRPC actions)
|
|
252
259
|
|
|
260
|
+
When accessing headers, the gateway first tries to get the header with the exact case provided by the user. If the header doesn't exist with that exact case, it falls back to looking for the same header name in lowercase. This behavior ensures compatibility with various HTTP clients that might send headers with different casing.
|
|
261
|
+
|
|
253
262
|
You can set headers for a specific action using `ApiServiceBaseActionConfig.proxyHeaders`:
|
|
254
263
|
|
|
255
264
|
```javascript
|
|
@@ -312,6 +321,9 @@ const config = {
|
|
|
312
321
|
includeProtoRoots: ['...'],
|
|
313
322
|
timeout: 25000, // default 25 seconds
|
|
314
323
|
caCertificatePath: '...',
|
|
324
|
+
// Optional: paths for mTLS client certificate and key
|
|
325
|
+
clientCertificatePath: '...',
|
|
326
|
+
clientKeyPath: '...',
|
|
315
327
|
};
|
|
316
328
|
|
|
317
329
|
const {api: gatewayApi} = getGatewayControllers({root: Schema}, config);
|
|
@@ -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;
|
|
22
|
+
export declare function getCredentialsMap(caCertificatePath?: string | null, clientCertificatePath?: string | null, clientKeyPath?: string | null): CredentialsMap;
|
|
23
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
|
};
|
|
@@ -108,7 +116,10 @@ function createMetadata({ options, actionConfig, config, params, serviceName, pr
|
|
|
108
116
|
}
|
|
109
117
|
for (const headerName of proxyHeaders) {
|
|
110
118
|
if (metadata[headerName] === undefined) {
|
|
111
|
-
metadata[headerName] =
|
|
119
|
+
metadata[headerName] =
|
|
120
|
+
headers[headerName] !== undefined
|
|
121
|
+
? headers[headerName]
|
|
122
|
+
: headers[headerName.toLowerCase()];
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
125
|
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)({
|
|
@@ -170,12 +181,37 @@ function clearInstancesCache(service, instancesMap, cachePath, closeTimeout, ctx
|
|
|
170
181
|
function getChannelCredential(config, endpointData, credentials) {
|
|
171
182
|
let endpointInsecure;
|
|
172
183
|
let endpointSecureWithoutRootCert;
|
|
184
|
+
let endpointCaCertificatePath;
|
|
185
|
+
let endpointClientCertificatePath;
|
|
186
|
+
let endpointClientKeyPath;
|
|
173
187
|
if ((0, common_2.isExtendedGrpcActionEndpoint)(endpointData)) {
|
|
174
188
|
endpointInsecure = endpointData === null || endpointData === void 0 ? void 0 : endpointData.insecure;
|
|
175
189
|
endpointSecureWithoutRootCert = endpointData === null || endpointData === void 0 ? void 0 : endpointData.secureWithoutRootCert;
|
|
190
|
+
endpointCaCertificatePath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.caCertificatePath;
|
|
191
|
+
endpointClientCertificatePath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.clientCertificatePath;
|
|
192
|
+
endpointClientKeyPath = endpointData === null || endpointData === void 0 ? void 0 : endpointData.clientKeyPath;
|
|
176
193
|
}
|
|
177
194
|
const isInsecure = config.insecure || endpointInsecure;
|
|
178
195
|
const isSecureWithoutRootCert = config.secureWithoutRootCert || endpointSecureWithoutRootCert;
|
|
196
|
+
// If endpoint-specific certificates are provided, create new credentials
|
|
197
|
+
if (endpointCaCertificatePath || endpointClientCertificatePath || endpointClientKeyPath) {
|
|
198
|
+
let certificate;
|
|
199
|
+
let clientCertificate;
|
|
200
|
+
let clientKey;
|
|
201
|
+
const caCertPath = endpointCaCertificatePath || config.caCertificatePath;
|
|
202
|
+
const clientCertPath = endpointClientCertificatePath || config.clientCertificatePath;
|
|
203
|
+
const clientKeyPath = endpointClientKeyPath || config.clientKeyPath;
|
|
204
|
+
if (caCertPath && fs_1.default.existsSync(caCertPath)) {
|
|
205
|
+
certificate = fs_1.default.readFileSync(caCertPath);
|
|
206
|
+
}
|
|
207
|
+
if (clientCertPath && fs_1.default.existsSync(clientCertPath)) {
|
|
208
|
+
clientCertificate = fs_1.default.readFileSync(clientCertPath);
|
|
209
|
+
}
|
|
210
|
+
if (clientKeyPath && fs_1.default.existsSync(clientKeyPath)) {
|
|
211
|
+
clientKey = fs_1.default.readFileSync(clientKeyPath);
|
|
212
|
+
}
|
|
213
|
+
return grpc.ChannelCredentials.createSsl(certificate, clientKey, clientCertificate);
|
|
214
|
+
}
|
|
179
215
|
let creds = credentials.secure;
|
|
180
216
|
if (isInsecure) {
|
|
181
217
|
creds = credentials.insecure;
|
package/build/components/rest.js
CHANGED
|
@@ -133,7 +133,10 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
|
|
|
133
133
|
}
|
|
134
134
|
for (const headerName of proxyHeaders) {
|
|
135
135
|
if (actionHeaders[headerName] === undefined) {
|
|
136
|
-
actionHeaders[headerName] =
|
|
136
|
+
actionHeaders[headerName] =
|
|
137
|
+
requestHeaders[headerName] !== undefined
|
|
138
|
+
? requestHeaders[headerName]
|
|
139
|
+
: requestHeaders[headerName.toLowerCase()];
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
142
|
if (requestId) {
|
package/build/index.js
CHANGED
|
@@ -259,7 +259,7 @@ function getGatewayControllers(schemasByScope, config) {
|
|
|
259
259
|
console.warn('Error when parse GATEWAY_ENDPOINTS_OVERRIDES', err);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
const credentials = (0, grpc_1.getCredentialsMap)(config.caCertificatePath);
|
|
262
|
+
const credentials = (0, grpc_1.getCredentialsMap)(config.caCertificatePath, config.clientCertificatePath, config.clientKeyPath);
|
|
263
263
|
for (const scope of (0, common_1.getKeys)(schemasByScope)) {
|
|
264
264
|
apiByScope[scope] = generateGatewayApi(schemasByScope[scope], config, { root: (0, grpc_1.createRoot)(config.includeProtoRoots), credentials }, apiByScope);
|
|
265
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;
|
|
@@ -274,6 +280,8 @@ export interface GatewayConfig<Context extends GatewayContext, Req extends Gatew
|
|
|
274
280
|
sendStats?: SendStats<Context>;
|
|
275
281
|
includeProtoRoots?: string[];
|
|
276
282
|
caCertificatePath: string | null;
|
|
283
|
+
clientCertificatePath?: string | null;
|
|
284
|
+
clientKeyPath?: string | null;
|
|
277
285
|
proxyHeaders: ProxyHeaders;
|
|
278
286
|
proxyDebugHeaders?: ProxyHeaders;
|
|
279
287
|
withDebugHeaders?: boolean | ((req: Req, res: Res) => boolean);
|