bare-http1 4.2.4 → 4.3.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.
Files changed (3) hide show
  1. package/index.d.ts +3 -0
  2. package/lib/agent.js +76 -50
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -99,6 +99,9 @@ export interface HTTPAgentOptions {
99
99
  }
100
100
 
101
101
  export interface HTTPAgent {
102
+ readonly sockets: IterableIterator<TCPSocket>
103
+ readonly freeSockets: IterableIterator<TCPSocket>
104
+
102
105
  createConnection(opts?: TCPSocketOptions & TCPSocketConnectOptions): TCPSocket
103
106
 
104
107
  reuseSocket(socket: TCPSocket, req?: HTTPClientRequest): void
package/lib/agent.js CHANGED
@@ -2,20 +2,77 @@ const EventEmitter = require('bare-events')
2
2
  const tcp = require('bare-tcp')
3
3
  const HTTPClientConnection = require('./client-connection')
4
4
 
5
+ class HTTPSocketSet {
6
+ constructor() {
7
+ this._sockets = new Map()
8
+ }
9
+
10
+ add(name, socket) {
11
+ const sockets = this._sockets.get(name)
12
+
13
+ if (sockets === undefined) this._sockets.set(name, [socket])
14
+ else sockets.push(socket)
15
+ }
16
+
17
+ pop(name) {
18
+ const sockets = this._sockets.get(name)
19
+ if (sockets === undefined || sockets.length === 0) return null
20
+
21
+ const last = sockets.pop()
22
+
23
+ if (sockets.length === 0) this._sockets.delete(name)
24
+
25
+ return last
26
+ }
27
+
28
+ delete(name, socket) {
29
+ const sockets = this._sockets.get(name)
30
+ if (sockets === undefined) return
31
+
32
+ const i = sockets.indexOf(socket)
33
+ if (i === -1) return
34
+
35
+ const last = sockets.pop()
36
+ if (last !== socket) sockets[i] = last
37
+
38
+ if (sockets.length === 0) this._sockets.delete(name)
39
+ }
40
+
41
+ *sockets() {
42
+ for (const sockets of this._sockets.values()) {
43
+ yield* sockets
44
+ }
45
+ }
46
+
47
+ *[Symbol.iterator]() {
48
+ for (const [name, sockets] of this._sockets) {
49
+ for (const socket of sockets) yield [name, socket]
50
+ }
51
+ }
52
+ }
53
+
5
54
  module.exports = class HTTPAgent extends EventEmitter {
6
55
  constructor(opts = {}) {
7
56
  super()
8
57
 
9
58
  const { keepAlive = false, keepAliveMsecs = 1000 } = opts
10
59
 
11
- this._sockets = new Map()
12
- this._freeSockets = new Map()
60
+ this._sockets = new HTTPSocketSet()
61
+ this._freeSockets = new HTTPSocketSet()
13
62
 
14
63
  this._keepAlive = typeof keepAlive === 'number' ? keepAlive : keepAlive ? keepAliveMsecs : -1
15
64
 
16
65
  this._opts = { ...opts }
17
66
  }
18
67
 
68
+ get sockets() {
69
+ return this._sockets.sockets()
70
+ }
71
+
72
+ get freeSockets() {
73
+ return this._freeSockets.sockets()
74
+ }
75
+
19
76
  createConnection(opts) {
20
77
  return tcp.createConnection(opts)
21
78
  }
@@ -42,33 +99,26 @@ module.exports = class HTTPAgent extends EventEmitter {
42
99
 
43
100
  const name = this.getName(opts)
44
101
 
45
- let socket
46
-
47
- if (this._freeSockets.has(name)) {
48
- const sockets = this._freeSockets.get(name)
49
-
50
- socket = sockets.pop()
102
+ let socket = this._freeSockets.pop(name)
51
103
 
52
- if (sockets.length === 0) this._freeSockets.delete(name)
53
-
54
- this.reuseSocket(socket, req)
55
- } else {
104
+ if (socket) this.reuseSocket(socket, req)
105
+ else {
56
106
  const agent = this
57
107
 
58
108
  socket = this.createConnection(opts)
59
109
 
60
- socket.on('free', onfree).on('end', onremove).on('finish', onremove).on('timeout', ontimeout)
110
+ socket
111
+ .on('free', onfree)
112
+ .on('end', onremove)
113
+ .on('finish', onremove)
114
+ .on('close', onremove)
115
+ .on('timeout', ontimeout)
61
116
 
62
117
  function onfree() {
63
118
  if (socket.destroyed) return
64
119
 
65
120
  if (agent.keepSocketAlive(socket)) {
66
- onremove(false)
67
-
68
- const sockets = agent._freeSockets.get(name)
69
-
70
- if (sockets === undefined) agent._freeSockets.set(name, [socket])
71
- else sockets.push(socket)
121
+ agent._freeSockets.add(name, socket)
72
122
  } else {
73
123
  socket.end()
74
124
  }
@@ -76,41 +126,19 @@ module.exports = class HTTPAgent extends EventEmitter {
76
126
  agent.emit('free', socket)
77
127
  }
78
128
 
79
- function onremove(destroy = true) {
80
- if (destroy) socket.off('free', onfree)
129
+ function onremove() {
130
+ socket.off('free', onfree)
81
131
 
82
- for (const set of destroy ? [agent._sockets, agent._freeSockets] : [agent._sockets]) {
83
- const sockets = set.get(name)
84
- if (sockets === undefined) continue
85
-
86
- const i = sockets.indexOf(socket)
87
- if (i === -1) continue
88
-
89
- const last = sockets.pop()
90
- if (last !== socket) sockets[i] = last
91
-
92
- if (sockets.length === 0) set.delete(name)
93
- }
132
+ agent._sockets.delete(name, socket)
133
+ agent._freeSockets.delete(name, socket)
94
134
  }
95
135
 
96
136
  function ontimeout() {
97
- const sockets = agent._freeSockets.get(name)
98
- if (sockets === undefined) return
99
-
100
- const i = sockets.indexOf(socket)
101
- if (i === -1) return
102
-
103
- const last = sockets.pop()
104
- if (last !== socket) sockets[i] = last
105
-
106
- if (sockets.length === 0) agent._freeSockets.delete(name)
137
+ agent._freeSockets.delete(name, socket)
107
138
  }
108
139
  }
109
140
 
110
- const sockets = this._sockets.get(name)
111
-
112
- if (sockets === undefined) this._sockets.set(name, [socket])
113
- else sockets.push(socket)
141
+ this._sockets.add(name, socket)
114
142
 
115
143
  req.socket = socket
116
144
 
@@ -121,9 +149,7 @@ module.exports = class HTTPAgent extends EventEmitter {
121
149
 
122
150
  destroy() {
123
151
  for (const set of [this._sockets, this._freeSockets]) {
124
- for (const [, sockets] of set) {
125
- for (const socket of sockets) socket.destroy()
126
- }
152
+ for (const socket of set) socket.destroy()
127
153
  }
128
154
  }
129
155
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-http1",
3
- "version": "4.2.4",
3
+ "version": "4.3.0",
4
4
  "description": "Native HTTP/1 library for JavaScript",
5
5
  "exports": {
6
6
  "./package": "./package.json",