@gravity-ui/gateway 2.0.0 → 2.1.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.
@@ -628,13 +628,30 @@ function createGrpcAction({ root, credentials }, endpoints, config, serviceKey,
628
628
  packageRoot: root,
629
629
  ErrorConstructor,
630
630
  });
631
- Object.assign(debugHeaders, (0, common_2.getHeadersFromMetadata)(trailingMetadata));
631
+ const responseHeaders = {};
632
+ if (config.proxyResponseHeaders) {
633
+ const proxyResponseHeaders = [];
634
+ const headersFromMetadata = (0, common_2.getHeadersFromMetadata)(trailingMetadata);
635
+ if (typeof config.proxyResponseHeaders === 'function') {
636
+ Object.assign(responseHeaders, config.proxyResponseHeaders(headersFromMetadata, 'grpc'));
637
+ }
638
+ else if (Array.isArray(config.proxyResponseHeaders)) {
639
+ proxyResponseHeaders.push(...config.proxyResponseHeaders);
640
+ }
641
+ for (const headerName of proxyResponseHeaders) {
642
+ if (responseHeaders[headerName] === undefined) {
643
+ responseHeaders[headerName] =
644
+ headersFromMetadata[headerName];
645
+ }
646
+ }
647
+ }
648
+ Object.assign(debugHeaders, (0, common_2.getHeadersFromMetadata)(trailingMetadata, 'x-metadata-'));
632
649
  sendStats(200, Object.assign(Object.assign({}, requestData), { responseSize: (0, object_sizeof_1.default)(response), grpcStatus: 0 }));
633
650
  ctx.log('Request completed', {
634
651
  debugHeaders: (0, common_2.sanitizeDebugHeaders)(debugHeaders),
635
652
  });
636
653
  ctx.end();
637
- return resolve({ responseData, debugHeaders });
654
+ return resolve({ responseData, responseHeaders, debugHeaders });
638
655
  });
639
656
  call.on('status', (status) => {
640
657
  trailingMetadata = status.metadata.toJSON();
@@ -3,5 +3,6 @@ import { GatewayContext } from '../models/context';
3
3
  import { AppErrorConstructor } from '../models/error';
4
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<{
5
5
  responseData: unknown;
6
+ responseHeaders?: Headers | undefined;
6
7
  debugHeaders: Headers;
7
8
  }>;
@@ -220,6 +220,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
220
220
  }
221
221
  try {
222
222
  const response = await axiosClient.request(requestConfig);
223
+ const responseHeaders = {};
223
224
  const endRequestTime = Date.now();
224
225
  requestData.requestTime = endRequestTime - startRequestTime;
225
226
  if (config.transformResponseData) {
@@ -235,6 +236,20 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
235
236
  (0, common_1.handleError)(ErrorConstructor, error, ctx, 'Transform response data failed');
236
237
  }
237
238
  }
239
+ if (config.proxyResponseHeaders) {
240
+ const proxyResponseHeaders = [];
241
+ if (typeof config.proxyResponseHeaders === 'function') {
242
+ Object.assign(responseHeaders, config.proxyResponseHeaders(Object.assign({}, response.headers), 'rest'));
243
+ }
244
+ else if (Array.isArray(config.proxyResponseHeaders)) {
245
+ proxyResponseHeaders.push(...config.proxyResponseHeaders);
246
+ }
247
+ for (const headerName of proxyResponseHeaders) {
248
+ if (responseHeaders[headerName] === undefined) {
249
+ responseHeaders[headerName] = response.headers[headerName];
250
+ }
251
+ }
252
+ }
238
253
  if (options === null || options === void 0 ? void 0 : options.sendStats) {
239
254
  options.sendStats(Object.assign(Object.assign({}, requestData), { responseSize: getRestResponseSize(response === null || response === void 0 ? void 0 : response.data, ctx, ErrorConstructor), restStatus: 200 }), (0, redact_sensitive_headers_1.redactSensitiveHeaders)(parentCtx, headers), parentCtx, { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
240
255
  }
@@ -243,7 +258,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
243
258
  }
244
259
  ctx.log('Request completed', { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
245
260
  ctx.end();
246
- return { responseData: response.data, debugHeaders };
261
+ return { responseData: response.data, responseHeaders, debugHeaders };
247
262
  }
248
263
  catch (error) {
249
264
  let parsedError;
package/build/index.js CHANGED
@@ -178,7 +178,7 @@ function generateGatewayApiController(schemasByScope, Api, config, controllerAct
178
178
  throw { error, debugHeaders: {} };
179
179
  }
180
180
  }
181
- const { responseData, debugHeaders } = await apiAction({
181
+ const { responseData, responseHeaders, debugHeaders } = await apiAction({
182
182
  requestId: req.id,
183
183
  headers: req.headers,
184
184
  ctx: req.ctx,
@@ -188,6 +188,9 @@ function generateGatewayApiController(schemasByScope, Api, config, controllerAct
188
188
  if (withDebugHeaders) {
189
189
  res.set(debugHeaders);
190
190
  }
191
+ if (responseHeaders) {
192
+ res.set(responseHeaders);
193
+ }
191
194
  if (onRequestSuccess) {
192
195
  return onRequestSuccess(req, res, responseData);
193
196
  }
@@ -62,6 +62,8 @@ export interface GatewayError {
62
62
  }
63
63
  export type ProxyHeadersFunction = (headers: IncomingHttpHeaders, type: ControllerType) => IncomingHttpHeaders;
64
64
  export type ProxyHeaders = string[] | ProxyHeadersFunction;
65
+ export type ProxyResponseHeadersFunction = (headers: Headers, type: ControllerType) => Headers;
66
+ export type ProxyResponseHeaders = string[] | ProxyResponseHeadersFunction;
65
67
  export type GetAuthHeadersParams<AuthArgs = Record<string, unknown>> = {
66
68
  actionType: 'rest' | 'grpc';
67
69
  serviceName: string;
@@ -114,6 +116,7 @@ export interface ApiServiceBaseActionConfig<Context extends GatewayContext, TOut
114
116
  retries?: number;
115
117
  idempotency?: boolean;
116
118
  proxyHeaders?: ProxyHeaders;
119
+ proxyResponseHeaders?: ProxyResponseHeaders;
117
120
  metadata?: Record<string, string | number | boolean>;
118
121
  }
119
122
  export interface ApiServiceRestActionConfig<Context extends GatewayContext, TOutput, TParams = undefined, TTransformed = TOutput> extends ApiServiceBaseActionConfig<Context, TOutput, TParams, TTransformed> {
@@ -185,6 +188,7 @@ export interface GatewayActionHeaders {
185
188
  }
186
189
  export interface GatewayActionUnaryResponse<TAction> extends GatewayActionHeaders {
187
190
  responseData: ApiActionResponseType<TAction>;
191
+ responseHeaders?: Headers;
188
192
  }
189
193
  export interface GatewayActionClientStreamResponse<TAction> extends GatewayActionHeaders {
190
194
  stream: ClientWritableStream<ApiActionResponseType<TAction>>;
@@ -11,5 +11,5 @@ export declare function getKeys<T extends object>(obj: T): (keyof T)[];
11
11
  * This function should only use to sanitize debugHeaders that are creating in our code
12
12
  */
13
13
  export declare function sanitizeDebugHeaders(debugHeaders: Headers): _.Omit<Headers, "x-api-request-body">;
14
- export declare function getHeadersFromMetadata(metadata: Record<string, grpc.MetadataValue[]>): Record<string, string>;
14
+ export declare function getHeadersFromMetadata(metadata: Record<string, grpc.MetadataValue[]>, prefix?: string): Record<string, string>;
15
15
  export declare function handleError<Context extends GatewayContext>(ErrorConstructor: AppErrorConstructor, error: unknown, ctx: Context, message: string, extra?: Dict): void;
@@ -30,11 +30,9 @@ function sanitizeDebugHeaders(debugHeaders) {
30
30
  return lodash_1.default.omit(debugHeaders, ['x-api-request-body']);
31
31
  }
32
32
  exports.sanitizeDebugHeaders = sanitizeDebugHeaders;
33
- function getHeadersFromMetadata(metadata) {
33
+ function getHeadersFromMetadata(metadata, prefix = '') {
34
34
  return Object.entries(metadata).reduce((headers, [key, values]) => {
35
- headers[`x-metadata-${key}`] = values
36
- .filter((value) => typeof value === 'string')
37
- .join(' ');
35
+ headers[`${prefix}${key}`] = values.filter((value) => typeof value === 'string').join(' ');
38
36
  return headers;
39
37
  }, {});
40
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/gateway",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",