Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b49a29a

Browse files
authored
feat: EventSource can be configured with reconnectionTime (#4260)
* feat: EventSource can be configured with node.reconnectionTime, deprecate dispatcher attribute on top level * no need for optional chaining * improve test
1 parent 8dd120e commit b49a29a

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

lib/web/eventsource/eventsource.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ class EventSource extends EventTarget {
124124
url = webidl.converters.USVString(url)
125125
eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix, 'eventSourceInitDict')
126126

127-
this.#dispatcher = eventSourceInitDict.dispatcher
127+
this.#dispatcher = eventSourceInitDict.node.dispatcher || eventSourceInitDict.dispatcher
128128
this.#state = {
129129
lastEventId: '',
130-
reconnectionTime: defaultReconnectionTime
130+
reconnectionTime: eventSourceInitDict.node.reconnectionTime
131131
}
132132

133133
// 2. Let settings be ev's relevant settings object.
@@ -472,6 +472,21 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
472472
{
473473
key: 'dispatcher', // undici only
474474
converter: webidl.converters.any
475+
},
476+
{
477+
key: 'node', // undici only
478+
converter: webidl.dictionaryConverter([
479+
{
480+
key: 'reconnectionTime',
481+
converter: webidl.converters['unsigned long'],
482+
defaultValue: () => defaultReconnectionTime
483+
},
484+
{
485+
key: 'dispatcher',
486+
converter: webidl.converters.any
487+
}
488+
]),
489+
defaultValue: () => ({})
475490
}
476491
])
477492

test/eventsource/eventsource-connect.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const assert = require('node:assert')
44
const events = require('node:events')
55
const http = require('node:http')
66
const { test, describe } = require('node:test')
7-
const { EventSource } = require('../../lib/web/eventsource/eventsource')
7+
const { EventSource, defaultReconnectionTime } = require('../../lib/web/eventsource/eventsource')
88
const { randomInt } = require('node:crypto')
99

1010
describe('EventSource - sending correct request headers', () => {
@@ -184,6 +184,7 @@ describe('EventSource - received response must have content-type to be text/even
184184
})
185185

186186
test('should try to connect again if server is unreachable', async () => {
187+
const reconnectionTime = defaultReconnectionTime
187188
const domain = 'bad.n' + randomInt(1e10).toString(36) + '.proxy'
188189

189190
const eventSourceInstance = new EventSource(`http://${domain}`)
@@ -192,11 +193,39 @@ describe('EventSource - received response must have content-type to be text/even
192193
eventSourceInstance.onerror = (error) => {
193194
onerrorCalls.push(error)
194195
}
196+
await events.once(eventSourceInstance, 'error')
195197

196-
await new Promise(resolve => setTimeout(resolve, 8000))
198+
const start = Date.now()
199+
await events.once(eventSourceInstance, 'error')
200+
await events.once(eventSourceInstance, 'error')
201+
await events.once(eventSourceInstance, 'error')
202+
const end = Date.now()
197203

198204
eventSourceInstance.close()
199205

200-
assert.strictEqual(onerrorCalls.length, 3)
206+
assert.strictEqual(end - start < (3.5 * reconnectionTime), true)
207+
})
208+
209+
test('should try to connect again if server is unreachable', async () => {
210+
const reconnectionTime = 500
211+
212+
const domain = 'bad.n' + randomInt(1e10).toString(36) + '.proxy'
213+
214+
const eventSourceInstance = new EventSource(`http://${domain}`, {
215+
node: {
216+
reconnectionTime
217+
}
218+
})
219+
await events.once(eventSourceInstance, 'error')
220+
221+
const start = Date.now()
222+
await events.once(eventSourceInstance, 'error')
223+
await events.once(eventSourceInstance, 'error')
224+
await events.once(eventSourceInstance, 'error')
225+
const end = Date.now()
226+
227+
eventSourceInstance.close()
228+
229+
assert.strictEqual(end - start < (3.5 * reconnectionTime), true)
201230
})
202231
})

test/eventsource/eventsource-custom-dispatcher.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,36 @@ test('EventSource allows setting custom dispatcher.', async (t) => {
3636

3737
await completed
3838
})
39+
40+
test('EventSource allows setting custom dispatcher in EventSourceDict.', async (t) => {
41+
const { completed, deepStrictEqual } = tspl(t, { plan: 1 })
42+
43+
const server = createServer({ joinDuplicateHeaders: true }, async (req, res) => {
44+
res.writeHead(200, 'OK', { 'Content-Type': 'text/event-stream' })
45+
deepStrictEqual(req.headers['x-customer-header'], 'hello world')
46+
47+
res.end()
48+
}).listen(0)
49+
50+
t.after(() => {
51+
server.close()
52+
eventSourceInstance.close()
53+
})
54+
55+
await once(server, 'listening')
56+
57+
class CustomHeaderAgent extends Agent {
58+
dispatch (opts) {
59+
opts.headers['x-customer-header'] = 'hello world'
60+
return super.dispatch(...arguments)
61+
}
62+
}
63+
64+
const eventSourceInstance = new EventSource(`http://localhost:${server.address().port}`, {
65+
node: {
66+
dispatcher: new CustomHeaderAgent()
67+
}
68+
})
69+
70+
await completed
71+
})

types/eventsource.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ export declare const EventSource: {
5656
}
5757

5858
interface EventSourceInit {
59-
withCredentials?: boolean,
59+
withCredentials?: boolean
60+
// @deprecated use `node.dispatcher` instead
6061
dispatcher?: Dispatcher
62+
node?: {
63+
dispatcher?: Dispatcher
64+
reconnectionTime?: number
65+
}
6166
}

0 commit comments

Comments
 (0)