@gravity-ui/gateway 1.0.0 → 1.0.2
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @gravity-ui/gateway · [](https://www.npmjs.com/package/@gravity-ui/gateway) [](https://github.com/gravity-ui/gateway/actions/workflows/ci.yml?query=branch:main)
|
|
2
2
|
|
|
3
|
-
Express controller for working with REST/GRPC APIs
|
|
3
|
+
Express controller for working with REST/GRPC APIs
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -17,9 +17,9 @@ import getGatewayControllers from '@gravity-ui/gateway';
|
|
|
17
17
|
import Schema from '<schemas package>';
|
|
18
18
|
|
|
19
19
|
const config = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
installation: 'external',
|
|
21
|
+
env: 'production',
|
|
22
|
+
includeProtoRoots: ['...'],
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const {controller: gatewayController} = getGatewayControllers({root: Schema}, config);
|
|
@@ -44,74 +44,84 @@ import {AxiosRequestConfig} from 'axios';
|
|
|
44
44
|
import {IncomingHttpHeaders} from 'http';
|
|
45
45
|
|
|
46
46
|
interface OnUnknownActionData {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
service?: string;
|
|
48
|
+
action?: string;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
interface Stats {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
service: string;
|
|
53
|
+
action: string;
|
|
54
|
+
restStatus: number;
|
|
55
|
+
grpcStatus?: number;
|
|
56
|
+
requestId: string;
|
|
57
|
+
requestTime: number;
|
|
58
|
+
requestMethod: string;
|
|
59
|
+
requestUrl: string;
|
|
60
|
+
timestamp: number;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
type SendStats = (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
stats: Stats,
|
|
65
|
+
headers: IncomingHttpHeaders,
|
|
66
|
+
ctx: CoreContext,
|
|
67
|
+
meta: {debugHeaders: Headers},
|
|
68
68
|
) => void;
|
|
69
69
|
|
|
70
|
-
type ProxyHeadersFunction = (
|
|
70
|
+
type ProxyHeadersFunction = (
|
|
71
|
+
headers: IncomingHttpHeaders,
|
|
72
|
+
type: ControllerType,
|
|
73
|
+
) => IncomingHttpHeaders;
|
|
71
74
|
type ProxyHeaders = string[] | ProxyHeadersFunction;
|
|
72
75
|
|
|
73
76
|
interface GatewayConfig {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
77
|
+
// Gateway Installation (external/internal/...). If the configuration is not provided, it is determined from process.env.APP_INSTALLATION.
|
|
78
|
+
installation?: string;
|
|
79
|
+
// Gateway Environment (production/testing/...). If the configuration is not provided, it is determined from process.env.APP_ENV.
|
|
80
|
+
env?: string;
|
|
81
|
+
// Additional gRPC client options.
|
|
82
|
+
grpcOptions?: object;
|
|
83
|
+
// Additional Axios client options.
|
|
84
|
+
axiosConfig?: AxiosRequestConfig;
|
|
85
|
+
// List of actions that need to be connected from the schema. By default, all actions are connected.
|
|
86
|
+
actions?: string[];
|
|
87
|
+
// Called when an unknown service or action is provided.
|
|
88
|
+
onUnknownAction?: (req: Request, res: Response, data: OnUnknownActionData) => any;
|
|
89
|
+
// Called before the request is executed.
|
|
90
|
+
onBeforeAction?: (
|
|
91
|
+
req: Request,
|
|
92
|
+
res: Response,
|
|
93
|
+
scope: string,
|
|
94
|
+
service: string,
|
|
95
|
+
action: string,
|
|
96
|
+
config?: ApiServiceActionConfig,
|
|
97
|
+
) => any;
|
|
98
|
+
// Called upon successful completion of the request.
|
|
99
|
+
onRequestSuccess?: (req: Request, res: Response, data: any) => any;
|
|
100
|
+
// Called in case of unsuccessful request execution.
|
|
101
|
+
onRequestFailed?: (req: Request, res: Response, error: any) => any;
|
|
102
|
+
// List of paths to the necessary proto files for the gateway.
|
|
103
|
+
includeProtoRoots?: string[];
|
|
104
|
+
// Configuration of the path to the certificate in gRPC.
|
|
105
|
+
// Set to null to use system certificates by default.
|
|
106
|
+
caCertificatePath?: string | null;
|
|
107
|
+
// Telemetry sending configuration.
|
|
108
|
+
sendStats?: SendStats;
|
|
109
|
+
// Configuration of headers sent to the API.
|
|
110
|
+
proxyHeaders?: ProxyHeaders;
|
|
111
|
+
// When passing a boolean value, it enables/disables debug headers in the response to the request.
|
|
112
|
+
// For unary requests to gRPC backends, debug headers will include information from the trailing metadata returned by the backend.
|
|
113
|
+
withDebugHeaders?: boolean;
|
|
114
|
+
// Validation schema for parameters used when no schema is present in the action. Documentation: https://ajv.js.org/json-schema.html#json-data-type
|
|
115
|
+
// You can use DEFAULT_VALIDATION_SCHEMA from lib/constants.ts.
|
|
116
|
+
validationSchema?: object;
|
|
117
|
+
// Enables encoding of REST path arguments.
|
|
118
|
+
encodePathArgs?: boolean;
|
|
119
|
+
// Configuration for automatic connection re-establishment upon connection error through L3 load balancer (default is false).
|
|
120
|
+
grpcRecreateService?: boolean;
|
|
111
121
|
}
|
|
112
122
|
```
|
|
113
123
|
|
|
114
|
-
###
|
|
124
|
+
### Usage in Node.js
|
|
115
125
|
|
|
116
126
|
Upon gateway initialization, in addition to exporting the controller, it also exports an `api` object, which represents the core for executing requests to the backend.
|
|
117
127
|
|
|
@@ -120,11 +130,11 @@ import getGatewayControllers from '@gravity-ui/gateway';
|
|
|
120
130
|
import Schema from '<schemas package>';
|
|
121
131
|
|
|
122
132
|
const config = {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
installation: 'external',
|
|
134
|
+
env: 'production',
|
|
135
|
+
includeProtoRoots: ['...'],
|
|
136
|
+
timeout: 25000, // default 25 seconds
|
|
137
|
+
caCertificatePath: '...',
|
|
128
138
|
};
|
|
129
139
|
|
|
130
140
|
const {api: gatewayApi} = getGatewayControllers({root: Schema}, config);
|
|
@@ -140,13 +150,13 @@ gatewayApi[service][action](actionConfig);
|
|
|
140
150
|
|
|
141
151
|
```typescript
|
|
142
152
|
interface ApiActionConfig<Context, TRequestData> {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
requestId: string;
|
|
154
|
+
headers: Headers;
|
|
155
|
+
args: TRequestData;
|
|
156
|
+
ctx: Context;
|
|
157
|
+
timeout?: number;
|
|
158
|
+
callback?: (response: TResponseData) => void;
|
|
159
|
+
authArgs?: Record<string, unknown>;
|
|
150
160
|
}
|
|
151
161
|
```
|
|
152
162
|
|
|
@@ -156,7 +166,7 @@ Each schema belongs to its own namespace. Service and action names between schem
|
|
|
156
166
|
The scope name is the key in the first parameter of the object containing the schemas.
|
|
157
167
|
|
|
158
168
|
```javascript
|
|
159
|
-
const schemasByScopes = {scope1: schema1, scope2: schema2}
|
|
169
|
+
const schemasByScopes = {scope1: schema1, scope2: schema2};
|
|
160
170
|
```
|
|
161
171
|
|
|
162
172
|
Example with two scope namespaces: `root` and `anotherScope`.
|
|
@@ -192,8 +202,6 @@ The controller for the expresskit will also expect the `:scope` parameter.
|
|
|
192
202
|
|
|
193
203
|
If the scope parameter is not specified, the default scope is assumed to be `root`.
|
|
194
204
|
|
|
195
|
-
|
|
196
|
-
|
|
197
205
|
### Connecting a Specific Set of Actions
|
|
198
206
|
|
|
199
207
|
When initializing the `gateway`, there is an option to explicitly specify the actions that need to be connected from the schemas. To do this, provide a list of available client-side actions in the `actions` field in the config. If `actions` are not provided, all actions from the schemas are connected by default.
|
|
@@ -204,10 +212,10 @@ import rootSchema from '<schemas package>';
|
|
|
204
212
|
import localSchema from '../shared/schemas';
|
|
205
213
|
|
|
206
214
|
const config = {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
installation: 'external',
|
|
216
|
+
env: 'production',
|
|
217
|
+
includeProtoRoots: ['...'],
|
|
218
|
+
actions: ['local.*', 'root.serviceA.*', 'root.serviceB.get'], // List of actions to be connected from the schemas. By default, all actions are connected.
|
|
211
219
|
};
|
|
212
220
|
|
|
213
221
|
const {api: gatewayApi} = getGatewayControllers({root: rootSchema, local: localSchema}, config);
|
|
@@ -215,7 +223,7 @@ const {api: gatewayApi} = getGatewayControllers({root: rootSchema, local: localS
|
|
|
215
223
|
|
|
216
224
|
The following combinations are available for specifying connected actions:
|
|
217
225
|
|
|
218
|
-
- `<scope>.*`
|
|
226
|
+
- `<scope>.*` - all actions from the scope scope are connected (for example, `local.*`)
|
|
219
227
|
- `<scope>.<service>.*` - all actions from the service service are connected (for example, `root.serviceA.*`)
|
|
220
228
|
- `<scope>.<service>.action` - only the specified action is connected (for example, `root.serviceB.get`)
|
|
221
229
|
|
|
@@ -236,11 +244,11 @@ To use reflection, you need to:
|
|
|
236
244
|
- Install the `grpc-reflection-js` package as a peer dependency.
|
|
237
245
|
- Apply patches to the `protobufjs` library. You can do this in the following ways:
|
|
238
246
|
|
|
239
|
-
|
|
247
|
+
a) Add `npx gateway-reflection-patch` to the `postinstall` script in your project and execute it. This assumes that protobufjs is located in the root of node_modules.
|
|
240
248
|
|
|
241
|
-
|
|
249
|
+
b) Copy the patch from the library's patches folder to your project's root, install [patch-package](https://www.npmjs.com/package/patch-package), and add the `patch-package` command to the `postinstall` script. In this case, you need to keep an eye on updates to the patches in the gateway when updating it.
|
|
242
250
|
|
|
243
|
-
|
|
251
|
+
If you encounter a "cannot run in wd [...]" error during Docker build, you can add unsafe-perm = true to your .npmrc file as described here.
|
|
244
252
|
|
|
245
253
|
- In the `action` configuration, replace the `protoPath` option with the `reflection` option and set its value to the appropriate `GrpcReflection` enum value. For reflection to work, the endpoint must support it.
|
|
246
254
|
|
|
@@ -260,10 +268,10 @@ This function is experimental. Fixes have been applied to `protobufjs` using [pa
|
|
|
260
268
|
- Fix for duplicated field [PR 1784](https://github.com/protobufjs/protobuf.js/pull/1784)
|
|
261
269
|
- Conversion of parameter names to camelCase [PR 1073](https://github.com/protobufjs/protobuf.js/pull/1073)
|
|
262
270
|
- Fix for handling Map [PR 1478](https://github.com/protobufjs/protobuf.js/pull/1478)
|
|
263
|
-
grpc-reflection-js has also been patched to support custom options.
|
|
271
|
+
grpc-reflection-js has also been patched to support custom options.
|
|
264
272
|
|
|
265
273
|
For development, you need to apply the patch locally using the command `npx patch-package`.
|
|
266
274
|
|
|
267
275
|
**ChannelCredentials Type Mismatch Error**
|
|
268
276
|
|
|
269
|
-
This error can occur due to duplicate installations of the
|
|
277
|
+
This error can occur due to duplicate installations of the `@grpc/grpc-js` library. It's recommended to ensure that all versions of this library are aligned and consistent to avoid this issue.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/gateway",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"axios-retry": "^3.4.0",
|
|
44
44
|
"lodash": "^4.17.21",
|
|
45
45
|
"object-sizeof": "^2.6.1",
|
|
46
|
-
"protobufjs": "^6.11.
|
|
46
|
+
"protobufjs": "^6.11.3",
|
|
47
47
|
"uuid": "^9.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
File without changes
|