@tramvai/module-request-limiter 1.89.1 → 1.90.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.
@@ -1,4 +1,5 @@
1
- import type { Request, Response, NextFunction } from 'express';
1
+ /// <reference types="node" />
2
+ import type { FastifyRequest, FastifyReply, HookHandlerDoneFunction } from 'fastify';
2
3
  export interface RequestLimiterOptions {
3
4
  limit?: number;
4
5
  queue?: number;
@@ -9,9 +10,9 @@ export interface RequestLimiterOptions {
9
10
  };
10
11
  }
11
12
  export interface RequestLimiterRequest {
12
- req: Request;
13
- res: Response;
14
- next: NextFunction;
13
+ req: FastifyRequest;
14
+ res: FastifyReply;
15
+ next: HookHandlerDoneFunction;
15
16
  }
16
17
  export declare class RequestLimiter {
17
18
  private currentActive;
@@ -24,8 +25,12 @@ export declare class RequestLimiter {
24
25
  private maxEventLoopDelay;
25
26
  private eventLoopHistogram;
26
27
  constructor(options?: RequestLimiterOptions);
28
+ onResponse(): void;
27
29
  private nextTick;
28
30
  add(request: RequestLimiterRequest): void;
29
31
  private loop;
30
32
  private run;
31
33
  }
34
+ export declare const fastifyRequestsLimiter: import("fastify").FastifyPluginAsync<{
35
+ requestsLimiter: RequestLimiter;
36
+ }, import("http").Server>;
package/lib/server.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { Module, provide, Scope } from '@tramvai/core';
3
- import { WEB_APP_LIMITER_TOKEN } from '@tramvai/tokens-server';
4
- import onFinished from 'on-finished';
3
+ import { WEB_FASTIFY_APP_LIMITER_TOKEN, WEB_FASTIFY_APP_TOKEN } from '@tramvai/tokens-server-private';
4
+ import fp from 'fastify-plugin';
5
5
  import { HttpError } from '@tinkoff/errors';
6
6
  import { monitorEventLoopDelay } from 'perf_hooks';
7
7
  import { createToken } from '@tinkoff/dippy';
@@ -89,7 +89,11 @@ class RequestLimiter {
89
89
  const timer = setInterval(() => this.nextTick(), 1000);
90
90
  timer.unref();
91
91
  }
92
- // General idea is change limits ever second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
92
+ onResponse() {
93
+ this.currentActive--;
94
+ this.loop();
95
+ }
96
+ // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
93
97
  nextTick() {
94
98
  this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
95
99
  if (Number.isNaN(this.eventLoopDelay))
@@ -122,16 +126,19 @@ class RequestLimiter {
122
126
  this.run(this.queue.pop());
123
127
  }
124
128
  }
125
- run({ req, res, next }) {
129
+ run({ next }) {
126
130
  this.currentActive++;
127
- // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
128
- onFinished(res, () => {
129
- this.currentActive--;
130
- this.loop();
131
- });
132
131
  next();
133
132
  }
134
133
  }
134
+ const fastifyRequestsLimiter = fp(async (fastify, { requestsLimiter }) => {
135
+ fastify.addHook('onRequest', (req, res, next) => {
136
+ requestsLimiter.add({ req, res, next });
137
+ });
138
+ fastify.addHook('onResponse', async () => {
139
+ requestsLimiter.onResponse();
140
+ });
141
+ });
135
142
 
136
143
  const REQUESTS_LIMITER_TOKEN = createToken('requestsLimiterToken');
137
144
  const REQUESTS_LIMITER_ACTIVATE_TOKEN = createToken('requestsLimiterActivateToken');
@@ -157,19 +164,18 @@ RequestLimiterModule = __decorate([
157
164
  },
158
165
  }),
159
166
  provide({
160
- provide: WEB_APP_LIMITER_TOKEN,
167
+ provide: WEB_FASTIFY_APP_LIMITER_TOKEN,
161
168
  multi: true,
162
- useFactory: ({ requestsLimiter, featureEnable }) => {
163
- return function addRequestsLimiterMiddleware(app) {
169
+ useFactory: ({ app, requestsLimiter, featureEnable }) => {
170
+ return async () => {
164
171
  if (featureEnable !== true) {
165
172
  return;
166
173
  }
167
- app.use((req, res, next) => {
168
- requestsLimiter.add({ req, res, next });
169
- });
174
+ await app.register(fastifyRequestsLimiter, { requestsLimiter });
170
175
  };
171
176
  },
172
177
  deps: {
178
+ app: WEB_FASTIFY_APP_TOKEN,
173
179
  requestsLimiter: REQUESTS_LIMITER_TOKEN,
174
180
  featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
175
181
  },
@@ -178,4 +184,4 @@ RequestLimiterModule = __decorate([
178
184
  })
179
185
  ], RequestLimiterModule);
180
186
 
181
- export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN, RequestLimiter, RequestLimiterModule };
187
+ export { REQUESTS_LIMITER_ACTIVATE_TOKEN, REQUESTS_LIMITER_OPTIONS_TOKEN, REQUESTS_LIMITER_TOKEN, RequestLimiter, RequestLimiterModule, fastifyRequestsLimiter };
package/lib/server.js CHANGED
@@ -4,15 +4,15 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tslib = require('tslib');
6
6
  var core = require('@tramvai/core');
7
- var tokensServer = require('@tramvai/tokens-server');
8
- var onFinished = require('on-finished');
7
+ var tokensServerPrivate = require('@tramvai/tokens-server-private');
8
+ var fp = require('fastify-plugin');
9
9
  var errors = require('@tinkoff/errors');
10
10
  var perf_hooks = require('perf_hooks');
11
11
  var dippy = require('@tinkoff/dippy');
12
12
 
13
13
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
14
 
15
- var onFinished__default = /*#__PURE__*/_interopDefaultLegacy(onFinished);
15
+ var fp__default = /*#__PURE__*/_interopDefaultLegacy(fp);
16
16
 
17
17
  class DoubleLinkedList {
18
18
  constructor() {
@@ -97,7 +97,11 @@ class RequestLimiter {
97
97
  const timer = setInterval(() => this.nextTick(), 1000);
98
98
  timer.unref();
99
99
  }
100
- // General idea is change limits ever second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
100
+ onResponse() {
101
+ this.currentActive--;
102
+ this.loop();
103
+ }
104
+ // General idea is change limits every second. Because if DDOS was happened we need some time to get problem with event loop. And better if we slowly adapt
101
105
  nextTick() {
102
106
  this.eventLoopDelay = Math.max(0, this.eventLoopHistogram.mean / 1e6 - resolution);
103
107
  if (Number.isNaN(this.eventLoopDelay))
@@ -130,16 +134,19 @@ class RequestLimiter {
130
134
  this.run(this.queue.pop());
131
135
  }
132
136
  }
133
- run({ req, res, next }) {
137
+ run({ next }) {
134
138
  this.currentActive++;
135
- // onFinished doesn't work OK in DEV mode. Just stuck with high load without any reasons
136
- onFinished__default["default"](res, () => {
137
- this.currentActive--;
138
- this.loop();
139
- });
140
139
  next();
141
140
  }
142
141
  }
142
+ const fastifyRequestsLimiter = fp__default["default"](async (fastify, { requestsLimiter }) => {
143
+ fastify.addHook('onRequest', (req, res, next) => {
144
+ requestsLimiter.add({ req, res, next });
145
+ });
146
+ fastify.addHook('onResponse', async () => {
147
+ requestsLimiter.onResponse();
148
+ });
149
+ });
143
150
 
144
151
  const REQUESTS_LIMITER_TOKEN = dippy.createToken('requestsLimiterToken');
145
152
  const REQUESTS_LIMITER_ACTIVATE_TOKEN = dippy.createToken('requestsLimiterActivateToken');
@@ -165,19 +172,18 @@ exports.RequestLimiterModule = tslib.__decorate([
165
172
  },
166
173
  }),
167
174
  core.provide({
168
- provide: tokensServer.WEB_APP_LIMITER_TOKEN,
175
+ provide: tokensServerPrivate.WEB_FASTIFY_APP_LIMITER_TOKEN,
169
176
  multi: true,
170
- useFactory: ({ requestsLimiter, featureEnable }) => {
171
- return function addRequestsLimiterMiddleware(app) {
177
+ useFactory: ({ app, requestsLimiter, featureEnable }) => {
178
+ return async () => {
172
179
  if (featureEnable !== true) {
173
180
  return;
174
181
  }
175
- app.use((req, res, next) => {
176
- requestsLimiter.add({ req, res, next });
177
- });
182
+ await app.register(fastifyRequestsLimiter, { requestsLimiter });
178
183
  };
179
184
  },
180
185
  deps: {
186
+ app: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
181
187
  requestsLimiter: REQUESTS_LIMITER_TOKEN,
182
188
  featureEnable: { token: REQUESTS_LIMITER_ACTIVATE_TOKEN, optional: true },
183
189
  },
@@ -190,3 +196,4 @@ exports.REQUESTS_LIMITER_ACTIVATE_TOKEN = REQUESTS_LIMITER_ACTIVATE_TOKEN;
190
196
  exports.REQUESTS_LIMITER_OPTIONS_TOKEN = REQUESTS_LIMITER_OPTIONS_TOKEN;
191
197
  exports.REQUESTS_LIMITER_TOKEN = REQUESTS_LIMITER_TOKEN;
192
198
  exports.RequestLimiter = RequestLimiter;
199
+ exports.fastifyRequestsLimiter = fastifyRequestsLimiter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-request-limiter",
3
- "version": "1.89.1",
3
+ "version": "1.90.1",
4
4
  "description": "Enable different rendering modes for pages",
5
5
  "main": "lib/server.js",
6
6
  "module": "lib/server.es.js",
@@ -25,16 +25,14 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@tinkoff/errors": "0.2.20",
28
- "on-finished": "^2.3.0"
29
- },
30
- "devDependencies": {
31
- "@types/express": "^4.17.9"
28
+ "fastify-plugin": "^3.0.1"
32
29
  },
30
+ "devDependencies": {},
33
31
  "peerDependencies": {
34
32
  "@tinkoff/dippy": "0.7.39",
35
- "@tramvai/core": "1.89.1",
36
- "@tramvai/tokens-server": "1.89.1",
37
- "express": "^4.17.1",
33
+ "@tramvai/core": "1.90.1",
34
+ "@tramvai/tokens-server-private": "1.90.1",
35
+ "fastify": "^3.0.0",
38
36
  "tslib": "^2.0.3"
39
37
  }
40
38
  }