bdy 1.23.8-master → 1.23.8

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,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.23.8-master",
4
+ "version": "1.23.8",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class LogThrottle {
4
+ interval;
5
+ reports = new Map();
6
+ onFlush;
7
+ timer = null;
8
+ // onFlush(kind, suppressed) - optional. Without it the tail of a burst is lost, which is fine for
9
+ // a throttle whose caller reports the count some other way, and wrong for every current caller.
10
+ constructor(interval, onFlush) {
11
+ this.interval = interval;
12
+ this.onFlush = onFlush || null;
13
+ if (this.onFlush) {
14
+ // unref: this sweep must never be the reason the agent stays alive after its tunnel is gone.
15
+ this.timer = setInterval(() => this.flush(), interval);
16
+ if (this.timer.unref)
17
+ this.timer.unref();
18
+ }
19
+ }
20
+ hit(kind) {
21
+ const now = Date.now();
22
+ const last = this.reports.get(kind);
23
+ if (last && now - last.at < this.interval) {
24
+ last.suppressed += 1;
25
+ return -1;
26
+ }
27
+ const suppressed = last ? last.suppressed : 0;
28
+ this.reports.set(kind, { at: now, suppressed: 0 });
29
+ return suppressed;
30
+ }
31
+ // Only kinds whose window has fully elapsed: one still inside its window is not quiet yet, and
32
+ // the next hit will carry its count the normal way. Deleting while iterating a Map is safe.
33
+ flush() {
34
+ if (!this.onFlush)
35
+ return;
36
+ const now = Date.now();
37
+ for (const [kind, last] of this.reports) {
38
+ if (now - last.at < this.interval)
39
+ continue;
40
+ if (!last.suppressed) {
41
+ this.reports.delete(kind);
42
+ continue;
43
+ }
44
+ const { suppressed } = last;
45
+ last.suppressed = 0;
46
+ last.at = now;
47
+ this.onFlush(kind, suppressed);
48
+ }
49
+ }
50
+ stop() {
51
+ if (!this.timer)
52
+ return;
53
+ clearInterval(this.timer);
54
+ this.timer = null;
55
+ }
56
+ }
57
+ exports.default = LogThrottle;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestIp = void 0;
4
+ const utils_1 = require("../../utils");
5
+ // The client address behind a request, from whichever place this channel carries it.
6
+ //
7
+ // Historically the address belonged to the CHANNEL: the worker put it in the 50-byte handshake and
8
+ // the agent set it as the channel's remoteAddress, which was exact because a channel served one
9
+ // client. Shared h2 channels break that - one channel now carries requests from many clients - so
10
+ // on those the worker sends the address per request instead.
11
+ //
12
+ // Which source to trust is decided by the channel's handshake type (`sharedIp`), never by the
13
+ // header being present. A worker old enough to open a non-shared channel is also old enough not to
14
+ // strip a client-supplied copy of the header, so trusting presence alone would let any client on
15
+ // such a tunnel dictate the address seen by the target app, the rate limiter, the request log and
16
+ // the PAT audit trail. Tie it to the channel and that whole class of confusion cannot arise.
17
+ const channelOf = (req) => req.httpVersion === '2.0' ? req.socket.stream : req.socket;
18
+ const requestIp = (req) => {
19
+ const channel = channelOf(req);
20
+ if (channel && channel.sharedIp) {
21
+ const claimed = req.headers ? req.headers[utils_1.TUNNEL_CLIENT_IP_HEADER] : null;
22
+ // A shared channel with no header means a worker bug, not a client one. '::1' matches what the
23
+ // legacy path already reports when it cannot resolve an address, so callers need no new case.
24
+ return (Array.isArray(claimed) ? claimed[0] : claimed) || '::1';
25
+ }
26
+ if (req.httpVersion === '2.0') {
27
+ return channel ? channel.remoteAddress : '::1';
28
+ }
29
+ return req.socket.remoteAddress;
30
+ };
31
+ exports.requestIp = requestIp;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.23.8-master",
4
+ "version": "1.23.8",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",