Skip to content

Commit 2c5bd18

Browse files
feat: add context to hooks (#407)
1 parent f63720b commit 2c5bd18

File tree

5 files changed

+55
-48
lines changed

5 files changed

+55
-48
lines changed

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,15 @@ See the example in [examples/reconnection](examples/reconnection).
249249

250250
## wsHooks
251251

252-
On websocket events, the following hooks are available, note **the hooks are all synchronous**.
252+
On websocket events, the following hooks are available, note **the hooks are all synchronous**.
253+
The `context` object is passed to all hooks and contains the `log` property.
253254

254-
- `onIncomingMessage`: A hook function that is called when the request is received from the client `onIncomingMessage(source, target, { data, binary })` (default: `undefined`).
255-
- `onOutgoingMessage`: A hook function that is called when the response is received from the target `onOutgoingMessage(source, target, { data, binary })` (default: `undefined`).
255+
- `onIncomingMessage`: A hook function that is called when the request is received from the client `onIncomingMessage(context, source, target, { data, binary })` (default: `undefined`).
256+
- `onOutgoingMessage`: A hook function that is called when the response is received from the target `onOutgoingMessage(context, source, target, { data, binary })` (default: `undefined`).
256257
- `onConnect`: A hook function that is called when the connection is established `onConnect(source, target)` (default: `undefined`).
257-
- `onDisconnect`: A hook function that is called when the connection is closed `onDisconnect(source)` (default: `undefined`).
258-
- `onReconnect`: A hook function that is called when the connection is reconnected `onReconnect(source, target)` (default: `undefined`). The function is called if reconnection feature is enabled.
259-
- `onPong`: A hook function that is called when the target responds to the ping `onPong(source, target)` (default: `undefined`). The function is called if reconnection feature is enabled.
258+
- `onDisconnect`: A hook function that is called when the connection is closed `onDisconnect(context, source)` (default: `undefined`).
259+
- `onReconnect`: A hook function that is called when the connection is reconnected `onReconnect(context, source, target)` (default: `undefined`). The function is called if reconnection feature is enabled.
260+
- `onPong`: A hook function that is called when the target responds to the ping `onPong(context, source, target)` (default: `undefined`). The function is called if reconnection feature is enabled.
260261

261262
## Benchmarks
262263

examples/reconnection/proxy/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async function main () {
4040
// clean backup from the last ping
4141
backup = backup.filter(message => message.timestamp > lastPong)
4242
},
43-
onIncomingMessage: (source, target, message) => {
43+
onIncomingMessage: (context, source, target, message) => {
4444
const m = message.data.toString()
4545
console.log('onIncomingMessage backup', m)
4646
backup.push({ message: m, timestamp: Date.now() })
@@ -49,7 +49,7 @@ async function main () {
4949
console.log('onDisconnect')
5050
backup.length = 0
5151
},
52-
onReconnect: (source, target) => {
52+
onReconnect: (context, source, target) => {
5353
console.log('onReconnect')
5454
resendMessages(target)
5555
},

index.js

+16-10
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,17 @@ function isExternalUrl (url) {
8282

8383
function noop () { }
8484

85+
function createContext (logger) {
86+
return { log: logger }
87+
}
88+
8589
function proxyWebSockets (logger, source, target, hooks) {
90+
const context = createContext(logger)
8691
function close (code, reason) {
8792
if (hooks.onDisconnect) {
8893
waitConnection(target, () => {
8994
try {
90-
hooks.onDisconnect(source)
95+
hooks.onDisconnect(context, source)
9196
} catch (err) {
9297
logger.error({ err }, 'proxy ws error from onDisconnect hook')
9398
}
@@ -100,7 +105,7 @@ function proxyWebSockets (logger, source, target, hooks) {
100105
source.on('message', (data, binary) => {
101106
if (hooks.onIncomingMessage) {
102107
try {
103-
hooks.onIncomingMessage(source, target, { data, binary })
108+
hooks.onIncomingMessage(context, source, target, { data, binary })
104109
} catch (err) {
105110
logger.error({ err }, 'proxy ws error from onIncomingMessage hook')
106111
}
@@ -121,7 +126,7 @@ function proxyWebSockets (logger, source, target, hooks) {
121126
target.on('message', (data, binary) => {
122127
if (hooks.onOutgoingMessage) {
123128
try {
124-
hooks.onOutgoingMessage(source, target, { data, binary })
129+
hooks.onOutgoingMessage(context, source, target, { data, binary })
125130
} catch (err) {
126131
logger.error({ err }, 'proxy ws error from onOutgoingMessage hook')
127132
}
@@ -141,7 +146,7 @@ function proxyWebSockets (logger, source, target, hooks) {
141146
if (hooks.onConnect) {
142147
waitConnection(target, () => {
143148
try {
144-
hooks.onConnect(source, target)
149+
hooks.onConnect(context, source, target)
145150
} catch (err) {
146151
logger.error({ err }, 'proxy ws error from onConnect hook')
147152
}
@@ -189,6 +194,7 @@ async function reconnect (logger, source, reconnectOptions, hooks, targetParams)
189194
}
190195

191196
function proxyWebSocketsWithReconnection (logger, source, target, options, hooks, targetParams, isReconnecting = false) {
197+
const context = createContext(logger)
192198
function close (code, reason) {
193199
target.pingTimer && clearInterval(target.pingTimer)
194200
target.pingTimer = undefined
@@ -206,7 +212,7 @@ function proxyWebSocketsWithReconnection (logger, source, target, options, hooks
206212

207213
if (hooks.onDisconnect) {
208214
try {
209-
hooks.onDisconnect(source)
215+
hooks.onDisconnect(context, source)
210216
} catch (err) {
211217
options.logs && logger.error({ target: targetParams.url, err }, 'proxy ws error from onDisconnect hook')
212218
}
@@ -231,7 +237,7 @@ function proxyWebSocketsWithReconnection (logger, source, target, options, hooks
231237
source.isAlive = true
232238
if (hooks.onIncomingMessage) {
233239
try {
234-
hooks.onIncomingMessage(source, target, { data, binary })
240+
hooks.onIncomingMessage(context, source, target, { data, binary })
235241
} catch (err) {
236242
logger.error({ target: targetParams.url, err }, 'proxy ws error from onIncomingMessage hook')
237243
}
@@ -281,7 +287,7 @@ function proxyWebSocketsWithReconnection (logger, source, target, options, hooks
281287
target.isAlive = true
282288
if (hooks.onOutgoingMessage) {
283289
try {
284-
hooks.onOutgoingMessage(source, target, { data, binary })
290+
hooks.onOutgoingMessage(context, source, target, { data, binary })
285291
} catch (err) {
286292
logger.error({ target: targetParams.url, err }, 'proxy ws error from onOutgoingMessage hook')
287293
}
@@ -296,7 +302,7 @@ function proxyWebSocketsWithReconnection (logger, source, target, options, hooks
296302
target.isAlive = true
297303
if (hooks.onPong) {
298304
try {
299-
hooks.onPong(source, target)
305+
hooks.onPong(context, source, target)
300306
} catch (err) {
301307
logger.error({ target: targetParams.url, err }, 'proxy ws error from onPong hook')
302308
}
@@ -336,13 +342,13 @@ function proxyWebSocketsWithReconnection (logger, source, target, options, hooks
336342
// call onConnect and onReconnect callbacks after the events are bound
337343
if (isReconnecting && hooks.onReconnect) {
338344
try {
339-
hooks.onReconnect(source, target)
345+
hooks.onReconnect(context, source, target)
340346
} catch (err) {
341347
options.logs && logger.error({ target: targetParams.url, err }, 'proxy ws error from onReconnect hook')
342348
}
343349
} else if (hooks.onConnect) {
344350
try {
345-
hooks.onConnect(source, target)
351+
hooks.onConnect(context, source, target)
346352
} catch (err) {
347353
options.logs && logger.error({ target: targetParams.url, err }, 'proxy ws error from onConnect hook')
348354
}

test/websocket.js

+13-13
Original file line numberDiff line numberDiff line change
@@ -716,18 +716,18 @@ test('multiple websocket upstreams with distinct server options', async (t) => {
716716
test('should call onIncomingMessage and onOutgoingMessage hooks', async (t) => {
717717
const request = 'query () { ... }'
718718
const response = 'data ...'
719-
const onIncomingMessage = (source, target, { data, binary }) => {
719+
const onIncomingMessage = (context, source, target, { data, binary }) => {
720720
assert.strictEqual(data.toString(), request)
721721
assert.strictEqual(binary, false)
722-
logger.info('onIncomingMessage called')
722+
context.log.info('onIncomingMessage called')
723723
}
724-
const onOutgoingMessage = (source, target, { data, binary }) => {
724+
const onOutgoingMessage = (context, source, target, { data, binary }) => {
725725
assert.strictEqual(data.toString(), response)
726726
assert.strictEqual(binary, false)
727-
logger.info('onOutgoingMessage called')
727+
context.log.info('onOutgoingMessage called')
728728
}
729729

730-
const { target, loggerSpy, logger, client } = await createServices({ t, wsHooks: { onIncomingMessage, onOutgoingMessage } })
730+
const { target, loggerSpy, client } = await createServices({ t, wsHooks: { onIncomingMessage, onOutgoingMessage } })
731731

732732
target.ws.on('connection', async (socket) => {
733733
socket.on('message', async (data, binary) => {
@@ -744,12 +744,12 @@ test('should call onIncomingMessage and onOutgoingMessage hooks', async (t) => {
744744
test('should handle throwing an error in onIncomingMessage and onOutgoingMessage hooks', async (t) => {
745745
const request = 'query () { ... }'
746746
const response = 'data ...'
747-
const onIncomingMessage = (source, target, { data, binary }) => {
747+
const onIncomingMessage = (context, source, target, { data, binary }) => {
748748
assert.strictEqual(data.toString(), request)
749749
assert.strictEqual(binary, false)
750750
throw new Error('onIncomingMessage error')
751751
}
752-
const onOutgoingMessage = (source, target, { data, binary }) => {
752+
const onOutgoingMessage = (context, source, target, { data, binary }) => {
753753
assert.strictEqual(data.toString(), response)
754754
assert.strictEqual(binary, false)
755755
throw new Error('onOutgoingMessage error')
@@ -770,11 +770,11 @@ test('should handle throwing an error in onIncomingMessage and onOutgoingMessage
770770
})
771771

772772
test('should call onConnect hook', async (t) => {
773-
const onConnect = () => {
774-
logger.info('onConnect called')
773+
const onConnect = (context) => {
774+
context.log.info('onConnect called')
775775
}
776776

777-
const { loggerSpy, logger } = await createServices({ t, wsHooks: { onConnect } })
777+
const { loggerSpy } = await createServices({ t, wsHooks: { onConnect } })
778778

779779
await waitForLogMessage(loggerSpy, 'onConnect called')
780780
})
@@ -790,11 +790,11 @@ test('should handle throwing an error in onConnect hook', async (t) => {
790790
})
791791

792792
test('should call onDisconnect hook', async (t) => {
793-
const onDisconnect = () => {
794-
logger.info('onDisconnect called')
793+
const onDisconnect = (context) => {
794+
context.log.info('onDisconnect called')
795795
}
796796

797-
const { loggerSpy, logger, client } = await createServices({ t, wsHooks: { onDisconnect } })
797+
const { loggerSpy, client } = await createServices({ t, wsHooks: { onDisconnect } })
798798
client.close()
799799

800800
await waitForLogMessage(loggerSpy, 'onDisconnect called')

test/ws-reconnect.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ test('should reconnect when the target connection is closed gracefully and recon
145145
})
146146

147147
test('should call onReconnect hook when the connection is reconnected', async (t) => {
148-
const onReconnect = (source, target) => {
149-
logger.info('onReconnect called')
148+
const onReconnect = (context, source, target) => {
149+
context.log.info('onReconnect called')
150150
}
151151
const wsReconnectOptions = {
152152
pingInterval: 100,
@@ -156,7 +156,7 @@ test('should call onReconnect hook when the connection is reconnected', async (t
156156
logs: true,
157157
}
158158

159-
const { target, loggerSpy, logger } = await createServices({ t, wsReconnectOptions, wsHooks: { onReconnect } })
159+
const { target, loggerSpy } = await createServices({ t, wsReconnectOptions, wsHooks: { onReconnect } })
160160

161161
target.ws.on('connection', async (socket) => {
162162
socket.on('ping', async () => {
@@ -173,7 +173,7 @@ test('should call onReconnect hook when the connection is reconnected', async (t
173173
})
174174

175175
test('should handle throwing an error in onReconnect hook', async (t) => {
176-
const onReconnect = (source, target) => {
176+
const onReconnect = () => {
177177
throw new Error('onReconnect error')
178178
}
179179
const wsReconnectOptions = {
@@ -203,15 +203,15 @@ test('should handle throwing an error in onReconnect hook', async (t) => {
203203
test('should call onIncomingMessage and onOutgoingMessage hooks, with reconnection', async (t) => {
204204
const request = 'query () { ... }'
205205
const response = 'data ...'
206-
const onIncomingMessage = (source, target, { data, binary }) => {
206+
const onIncomingMessage = (context, source, target, { data, binary }) => {
207207
assert.strictEqual(data.toString(), request)
208208
assert.strictEqual(binary, false)
209-
logger.info('onIncomingMessage called')
209+
context.log.info('onIncomingMessage called')
210210
}
211-
const onOutgoingMessage = (source, target, { data, binary }) => {
211+
const onOutgoingMessage = (context, source, target, { data, binary }) => {
212212
assert.strictEqual(data.toString(), response)
213213
assert.strictEqual(binary, false)
214-
logger.info('onOutgoingMessage called')
214+
context.log.info('onOutgoingMessage called')
215215
}
216216
const wsReconnectOptions = {
217217
pingInterval: 100,
@@ -220,7 +220,7 @@ test('should call onIncomingMessage and onOutgoingMessage hooks, with reconnecti
220220
logs: true,
221221
}
222222

223-
const { target, loggerSpy, logger, client } = await createServices({ t, wsReconnectOptions, wsHooks: { onIncomingMessage, onOutgoingMessage } })
223+
const { target, loggerSpy, client } = await createServices({ t, wsReconnectOptions, wsHooks: { onIncomingMessage, onOutgoingMessage } })
224224

225225
target.ws.on('connection', async (socket) => {
226226
socket.on('message', async (data, binary) => {
@@ -237,12 +237,12 @@ test('should call onIncomingMessage and onOutgoingMessage hooks, with reconnecti
237237
test('should handle throwing an error in onIncomingMessage and onOutgoingMessage hooks, with reconnection', async (t) => {
238238
const request = 'query () { ... }'
239239
const response = 'data ...'
240-
const onIncomingMessage = ({ data, binary }) => {
240+
const onIncomingMessage = (context, source, target, { data, binary }) => {
241241
assert.strictEqual(data.toString(), request)
242242
assert.strictEqual(binary, false)
243243
throw new Error('onIncomingMessage error')
244244
}
245-
const onOutgoingMessage = ({ data, binary }) => {
245+
const onOutgoingMessage = (context, source, target, { data, binary }) => {
246246
assert.strictEqual(data.toString(), response)
247247
assert.strictEqual(binary, false)
248248
throw new Error('onOutgoingMessage error')
@@ -269,15 +269,15 @@ test('should handle throwing an error in onIncomingMessage and onOutgoingMessage
269269
})
270270

271271
test('should call onConnect hook', async (t) => {
272-
const onConnect = () => {
273-
logger.info('onConnect called')
272+
const onConnect = (context) => {
273+
context.log.info('onConnect called')
274274
}
275275

276276
const wsReconnectOptions = {
277277
logs: true,
278278
}
279279

280-
const { loggerSpy, logger } = await createServices({ t, wsReconnectOptions, wsHooks: { onConnect } })
280+
const { loggerSpy } = await createServices({ t, wsReconnectOptions, wsHooks: { onConnect } })
281281

282282
await waitForLogMessage(loggerSpy, 'onConnect called')
283283
})
@@ -297,15 +297,15 @@ test('should handle throwing an error in onConnect hook', async (t) => {
297297
})
298298

299299
test('should call onDisconnect hook', async (t) => {
300-
const onDisconnect = () => {
301-
logger.info('onDisconnect called')
300+
const onDisconnect = (context) => {
301+
context.log.info('onDisconnect called')
302302
}
303303

304304
const wsReconnectOptions = {
305305
logs: true,
306306
}
307307

308-
const { loggerSpy, logger, client } = await createServices({ t, wsReconnectOptions, wsHooks: { onDisconnect } })
308+
const { loggerSpy, client } = await createServices({ t, wsReconnectOptions, wsHooks: { onDisconnect } })
309309
client.close()
310310

311311
await waitForLogMessage(loggerSpy, 'onDisconnect called')

0 commit comments

Comments
 (0)