@gravity-ui/gateway 4.10.4 → 4.11.1

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.
@@ -515,7 +515,7 @@ function createGrpcAction({ root, credentials }, endpoints, config, serviceKey,
515
515
  let stopListeningForAbort = null;
516
516
  // eslint-disable-next-line complexity
517
517
  return new Promise((resolve, reject) => {
518
- var _a, _b, _c, _d;
518
+ var _a, _b, _c, _d, _e;
519
519
  let endpointData = (endpoints === null || endpoints === void 0 ? void 0 : endpoints.grpcEndpoint) || (endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpoint);
520
520
  if (typeof config.endpoint === 'function') {
521
521
  endpointData = config.endpoint(endpoints, args);
@@ -662,7 +662,7 @@ function createGrpcAction({ root, credentials }, endpoints, config, serviceKey,
662
662
  ctx.log('Starting unary request', {
663
663
  debugHeaders: (0, common_2.sanitizeDebugHeaders)(debugHeaders),
664
664
  });
665
- let retries = (_d = config.retries) !== null && _d !== void 0 ? _d : 0;
665
+ let retries = (_e = (_d = actionConfig.retries) !== null && _d !== void 0 ? _d : config.retries) !== null && _e !== void 0 ? _e : 0;
666
666
  let actionCall = service[action].bind(service);
667
667
  const callAction = () => {
668
668
  let trailingMetadata = {};
@@ -11,6 +11,7 @@ const constants_1 = require("../constants");
11
11
  const axios_1 = require("../utils/axios");
12
12
  const common_1 = require("../utils/common");
13
13
  const parse_error_1 = require("../utils/parse-error");
14
+ const pipe_through_byte_counter_1 = require("../utils/pipe-through-byte-counter");
14
15
  const redact_sensitive_headers_1 = require("../utils/redact-sensitive-headers");
15
16
  const validate_1 = require("../utils/validate");
16
17
  function getRestResponseSize(data, ctx, ErrorConstructor) {
@@ -39,7 +40,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
39
40
  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
41
  /* eslint-disable complexity */
41
42
  return async function action(actionConfig) {
42
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
43
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
43
44
  const { args, requestId, headers: requestHeaders, ctx: parentCtx, authArgs, userId, abortSignal, } = actionConfig;
44
45
  const debugHeaders = {};
45
46
  const lang = requestHeaders[constants_1.DEFAULT_LANG_HEADER] || constants_1.Lang.Ru; // header might be empty string
@@ -206,9 +207,10 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
206
207
  const startRequestTime = Date.now();
207
208
  let axiosClient = defaultAxiosClient;
208
209
  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;
209
- if (actionConfig.timeout || endpointAxiosConfig) {
210
+ const customActionRetries = (_g = actionConfig.retries) !== null && _g !== void 0 ? _g : config.retries;
211
+ if (actionConfig.timeout || actionConfig.retries || endpointAxiosConfig) {
210
212
  const customActionAxiosConfig = Object.assign(Object.assign({}, ((options === null || options === void 0 ? void 0 : options.axiosConfig) || {})), (endpointAxiosConfig || {}));
211
- 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);
213
+ axiosClient = (0, axios_1.getAxiosClient)(customActionTimeout, customActionRetries, (_h = config === null || config === void 0 ? void 0 : config.axiosRetryCondition) !== null && _h !== void 0 ? _h : options === null || options === void 0 ? void 0 : options.axiosRetryCondition, customActionAxiosConfig, options === null || options === void 0 ? void 0 : options.axiosInterceptors);
212
214
  }
213
215
  headers['x-request-timeout'] = customActionTimeout !== null && customActionTimeout !== void 0 ? customActionTimeout : constants_1.DEFAULT_TIMEOUT;
214
216
  ctx.log('Starting request', { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
@@ -219,7 +221,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
219
221
  requestId,
220
222
  requestMethod: config.method,
221
223
  requestUrl: actionURL,
222
- traceId: ((_g = ctx.getTraceId) === null || _g === void 0 ? void 0 : _g.call(ctx)) || '',
224
+ traceId: ((_j = ctx.getTraceId) === null || _j === void 0 ? void 0 : _j.call(ctx)) || '',
223
225
  userId: userId || '',
224
226
  };
225
227
  const requestConfig = {
@@ -246,7 +248,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
246
248
  const responseHeaders = {};
247
249
  const endRequestTime = Date.now();
248
250
  requestData.requestTime = endRequestTime - startRequestTime;
249
- const actualResponseContentType = (_h = response.headers) === null || _h === void 0 ? void 0 : _h['Content-Type'];
251
+ const actualResponseContentType = (_k = response.headers) === null || _k === void 0 ? void 0 : _k['Content-Type'];
250
252
  const expectedResponseContentType = config.expectedResponseContentType || options.expectedResponseContentType;
251
253
  if (actualResponseContentType && expectedResponseContentType) {
252
254
  let isInvalidResponseContentType;
@@ -305,7 +307,16 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
305
307
  }
306
308
  }
307
309
  if (options === null || options === void 0 ? void 0 : options.sendStats) {
308
- 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) });
310
+ const emitStats = (responseSize, restStatus) => {
311
+ var _a;
312
+ return (_a = options.sendStats) === null || _a === void 0 ? void 0 : _a.call(options, Object.assign(Object.assign({}, requestData), { responseSize, restStatus }), (0, redact_sensitive_headers_1.redactSensitiveHeaders)(parentCtx, headers), parentCtx, { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
313
+ };
314
+ if (response.data && typeof response.data.pipe === 'function') {
315
+ response.data = (0, pipe_through_byte_counter_1.pipeThroughByteCounter)(response.data, (streamedBytes) => emitStats(streamedBytes, 200));
316
+ }
317
+ else {
318
+ emitStats(getRestResponseSize(response === null || response === void 0 ? void 0 : response.data, ctx, ErrorConstructor), 200);
319
+ }
309
320
  }
310
321
  else {
311
322
  ctx.stats(Object.assign(Object.assign({}, requestData), { responseStatus: 200 }));
@@ -343,7 +354,7 @@ function createRestAction(endpoints, config, serviceKey, actionName, options, Er
343
354
  }
344
355
  const responseStatus = lodash_1.default.get(parsedError, 'status') || lodash_1.default.get(error, 'status', 500);
345
356
  if (options === null || options === void 0 ? void 0 : options.sendStats) {
346
- 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) });
357
+ options.sendStats(Object.assign(Object.assign({}, requestData), { responseSize: getRestResponseSize((_l = error === null || error === void 0 ? void 0 : error.response) === null || _l === void 0 ? void 0 : _l.data, ctx, ErrorConstructor), restStatus: responseStatus, userId }), (0, redact_sensitive_headers_1.redactSensitiveHeaders)(parentCtx, headers), parentCtx, { debugHeaders: (0, common_1.sanitizeDebugHeaders)(debugHeaders) });
347
358
  }
348
359
  else {
349
360
  ctx.stats(Object.assign(Object.assign({}, requestData), { responseStatus }));
@@ -29,6 +29,7 @@ export interface ApiActionConfig<Context extends GatewayContext, TRequestData, T
29
29
  args: TRequestData;
30
30
  ctx: Context;
31
31
  timeout?: number;
32
+ retries?: number;
32
33
  callback?: (response: TResponseData) => void;
33
34
  authArgs?: Record<string, unknown>;
34
35
  userId?: string;
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type { Readable } from 'stream';
4
+ export declare function pipeThroughByteCounter(source: NodeJS.ReadableStream, onFlush: (streamedBytes: number) => void): Readable;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pipeThroughByteCounter = void 0;
4
+ const stream_1 = require("stream");
5
+ function pipeThroughByteCounter(source, onFlush) {
6
+ let streamedBytes = 0;
7
+ const counter = new stream_1.Transform({
8
+ transform(chunk, encoding, cb) {
9
+ if (Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {
10
+ streamedBytes += chunk.length;
11
+ }
12
+ else if (typeof chunk === 'string') {
13
+ streamedBytes += Buffer.byteLength(chunk, typeof encoding === 'string' ? encoding : undefined);
14
+ }
15
+ cb(null, chunk);
16
+ },
17
+ flush(cb) {
18
+ onFlush(streamedBytes);
19
+ cb();
20
+ },
21
+ });
22
+ return source.pipe(counter);
23
+ }
24
+ exports.pipeThroughByteCounter = pipeThroughByteCounter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/gateway",
3
- "version": "4.10.4",
3
+ "version": "4.11.1",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",