Codebase list node-eventsource / c7b2f98
New upstream snapshot. Debian Janitor 2 years ago
15 changed file(s) with 43 addition(s) and 1351 deletion(s). Raw diff Collapse all Expand all
+0
-3
.npmignore less more
0 test/
1 .nyc_output/
2 coverage/
0 # [1.1.0](https://github.com/EventSource/eventsource/compare/v1.0.7...v1.1.0)
1
2 * Improve performance for large messages across many chunks ([#130](https://github.com/EventSource/eventsource/pull/130) Trent Willis)
3 * Add `createConnection` option for http or https requests ([#120](https://github.com/EventSource/eventsource/pull/120) Vasily Lavrov)
4 * Support HTTP 302 redirects ([#116](https://github.com/EventSource/eventsource/pull/116) Ryan Bonte)
5 * Prevent sequential errors from attempting multiple reconnections ([#125](https://github.com/EventSource/eventsource/pull/125) David Patty)
6 * Add `new` to correct test ([#111](https://github.com/EventSource/eventsource/pull/101) Stéphane Alnet)
7 * Fix reconnections attempts now happen more than once ([#136](https://github.com/EventSource/eventsource/pull/136) Icy Fish)
8
09 # [1.0.7](https://github.com/EventSource/eventsource/compare/v1.0.6...v1.0.7)
110
211 * Add dispatchEvent to EventSource ([#101](https://github.com/EventSource/eventsource/pull/101) Ali Afroozeh)
0 # EventSource [![npm version](http://img.shields.io/npm/v/eventsource.svg?style=flat-square)](http://browsenpm.org/package/eventsource)[![Build Status](http://img.shields.io/travis/EventSource/eventsource/master.svg?style=flat-square)](https://travis-ci.org/EventSource/eventsource)[![NPM Downloads](https://img.shields.io/npm/dm/eventsource.svg?style=flat-square)](http://npm-stat.com/charts.html?package=eventsource&from=2015-09-01)[![Dependencies](https://img.shields.io/david/EventSource/eventsource.svg?style=flat-square)](https://david-dm.org/EventSource/eventsource)
0 # EventSource [![npm version](http://img.shields.io/npm/v/eventsource.svg?style=flat-square)](https://www.npmjs.com/package/eventsource)[![NPM Downloads](https://img.shields.io/npm/dm/eventsource.svg?style=flat-square)](http://npm-stat.com/charts.html?package=eventsource&from=2015-09-01)[![Dependencies](https://img.shields.io/david/EventSource/eventsource.svg?style=flat-square)](https://david-dm.org/EventSource/eventsource)
1
2 ![Build](https://github.com/EventSource/eventsource/actions/workflows/build.yml/badge.svg)
13
24 This library is a pure JavaScript implementation of the [EventSource](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) client. The API aims to be W3C compatible.
35
0 node-eventsource (1.1.0+git20210508.1.82e0343-1) UNRELEASED; urgency=low
1
2 * New upstream snapshot.
3
4 -- Debian Janitor <janitor@jelmer.uk> Wed, 17 Nov 2021 10:57:51 -0000
5
06 node-eventsource (1.0.7-1) unstable; urgency=medium
17
28 * Team upload
37633763 self.url = response.url
37643764 self.statusCode = response.status
37653765 self.statusMessage = response.statusText
3766
3766
37673767 response.headers.forEach(function (header, key){
37683768 self.headers[key.toLowerCase()] = header
37693769 self.rawHeaders.push(key, header)
38933893 self.push(new Buffer(response))
38943894 break
38953895 }
3896 // Falls through in IE8
3896 // Falls through in IE8
38973897 case 'text':
38983898 try { // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4
38993899 response = xhr.responseText
64566456 }
64576457
64586458 // Handle HTTP redirects
6459 if (res.statusCode === 301 || res.statusCode === 307) {
6459 if (res.statusCode === 301 || res.statusCode === 302 || res.statusCode === 307) {
64606460 if (!res.headers.location) {
64616461 // Server sent redirect response without Location header.
64626462 _emit('error', new Event('error', {status: res.statusCode}))
1008410084
1008510085
1008610086 /***/ })
10087 /******/ ]);
10087 /******/ ]);
4444
4545 var self = this
4646 self.reconnectInterval = 1000
47 self.connectionInProgress = false
4748
4849 function onConnectionClosed (message) {
4950 if (readyState === EventSource.CLOSED) return
5758 reconnectUrl = null
5859 }
5960 setTimeout(function () {
60 if (readyState !== EventSource.CONNECTING) {
61 if (readyState !== EventSource.CONNECTING || self.connectionInProgress) {
6162 return
6263 }
64 self.connectionInProgress = true
6365 connect()
6466 }, self.reconnectInterval)
6567 }
9597 // but for now exists as a backwards-compatibility layer
9698 options.rejectUnauthorized = !(eventSourceInitDict && !eventSourceInitDict.rejectUnauthorized)
9799
100 if (eventSourceInitDict && eventSourceInitDict.createConnection !== undefined) {
101 options.createConnection = eventSourceInitDict.createConnection
102 }
103
98104 // If specify http proxy, make the request to sent to the proxy server,
99105 // and include the original url in path and Host headers
100106 var useProxy = eventSourceInitDict && eventSourceInitDict.proxy
130136 }
131137
132138 req = (isSecure ? https : http).request(options, function (res) {
139 self.connectionInProgress = false
133140 // Handle HTTP errors
134141 if (res.statusCode === 500 || res.statusCode === 502 || res.statusCode === 503 || res.statusCode === 504) {
135142 _emit('error', new Event('error', {status: res.statusCode, message: res.statusMessage}))
138145 }
139146
140147 // Handle HTTP redirects
141 if (res.statusCode === 301 || res.statusCode === 307) {
148 if (res.statusCode === 301 || res.statusCode === 302 || res.statusCode === 307) {
142149 if (!res.headers.location) {
143150 // Server sent redirect response without Location header.
144151 _emit('error', new Event('error', {status: res.statusCode, message: res.statusMessage}))
173180 // Source/WebCore/page/EventSource.cpp
174181 var isFirst = true
175182 var buf
183 var startingPos = 0
184 var startingFieldLength = -1
176185 res.on('data', function (chunk) {
177186 buf = buf ? Buffer.concat([buf, chunk]) : chunk
178187 if (isFirst && hasBom(buf)) {
192201 }
193202
194203 var lineLength = -1
195 var fieldLength = -1
204 var fieldLength = startingFieldLength
196205 var c
197206
198 for (var i = pos; lineLength < 0 && i < length; ++i) {
207 for (var i = startingPos; lineLength < 0 && i < length; ++i) {
199208 c = buf[i]
200209 if (c === colon) {
201210 if (fieldLength < 0) {
210219 }
211220
212221 if (lineLength < 0) {
222 startingPos = length - pos
223 startingFieldLength = fieldLength
213224 break
225 } else {
226 startingPos = 0
227 startingFieldLength = -1
214228 }
215229
216230 parseEventStreamLine(buf, pos, fieldLength, lineLength)
227241 })
228242
229243 req.on('error', function (err) {
244 self.connectionInProgress = false
230245 onConnectionClosed(err.message)
231246 })
232247
00 {
11 "name": "eventsource",
2 "version": "1.0.7",
2 "version": "1.1.0",
33 "description": "W3C compliant EventSource client for Node.js and browser (polyfill)",
44 "keywords": [
55 "eventsource",
4545 "coverage": "nyc --reporter=html --reporter=text _mocha --reporter spec"
4646 },
4747 "engines": {
48 "node": ">=0.12.0"
48 "node": ">=12.0.0"
4949 },
5050 "dependencies": {
5151 "original": "^1.0.0"
+0
-13
test/client_certs/cacert.crt less more
0 -----BEGIN CERTIFICATE-----
1 MIICBzCCAXACCQDe3kCVnwXlKTANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJV
2 UzELMAkGA1UECBMCVkExFDASBgNVBAoTC0V2ZW50U291cmNlMRYwFAYDVQQDEw1F
3 dmVudFNvdXJjZUNBMB4XDTE2MDIyOTIwMTMyNloXDTI2MDIyNjIwMTMyNlowSDEL
4 MAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRQwEgYDVQQKEwtFdmVudFNvdXJjZTEW
5 MBQGA1UEAxMNRXZlbnRTb3VyY2VDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
6 gYEAujWjBi18dawJfTPMd1vtozoE0VRD5aP32d2UU3kps8nDfKlwcWcaYcKtGhlT
7 KXYKn4zrXd6wa5J3RdWEwukN5aAkLYDPCJX12w8KacDOoqdYyHi635QXXq1N+7rK
8 nDKaDwtg015fPsOumLDqk6x4VBpFDbjrcblT0ILqsurd0OMCAwEAATANBgkqhkiG
9 9w0BAQUFAAOBgQABgZZnsnsDsGctScBD7vSoTM9+aOetlUlPZx6N52ADe1L77rP7
10 0rPxL/+yD3VGVTAhAHrtC1JpJpo+JBssuC2EkwZ2RWFU/rkYQBO7wbgRFAoEWylT
11 j3PaeDzUZumSL5ZuVyQC94XNCodNeWBDK+WzQbjPa0BPd6vflUnAb/stwg==
12 -----END CERTIFICATE-----
+0
-13
test/client_certs/client_cert.crt less more
0 -----BEGIN CERTIFICATE-----
1 MIICAjCCAWsCCQDcY7oXL2AdXjANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJV
2 UzELMAkGA1UECBMCVkExFDASBgNVBAoTC0V2ZW50U291cmNlMRYwFAYDVQQDEw1F
3 dmVudFNvdXJjZUNBMB4XDTE2MDIyOTIwMTU0MVoXDTI2MDIyNjIwMTU0MVowQzEL
4 MAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRQwEgYDVQQKEwtFdmVudFNvdXJjZTER
5 MA8GA1UEAxMIdGVzdHVzZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPKw
6 mifd5tbJg5ZDkoabQsgqqu24MsNbJMtrbTkH/DtK12Qg6m5n8TR2aUt/CfpXBNkh
7 C40KzbFirkoTwLtLon39f6HFqaQCvdRZOb9e3SmHapm1W/ROx2M4L17DdKaVdkVn
8 7HA4zBL+kfZSI914dWTI4s0l9ohwJdVmBBBsmEO9AgMBAAEwDQYJKoZIhvcNAQEF
9 BQADgYEAdDfnGB9/n3Q2Hao4t8svM5s/Wyvy/sc8iZUn4R6PwFKSmeeuOS6NjkIy
10 rq59z3D4qHTES5RFoO7d8km884UcYCz6mq081hAm+Dlcd3uZhsWyboHCgkWlhVIS
11 XGEeNAUBir6aGvBkfU69HFdXfprTiTvHlt2NukwTPCYoqPQQH3w=
12 -----END CERTIFICATE-----
+0
-18
test/client_certs/client_key.pem less more
0 -----BEGIN RSA PRIVATE KEY-----
1 Proc-Type: 4,ENCRYPTED
2 DEK-Info: DES-EDE3-CBC,6040D9A5C438CD94
3
4 nIsbCSSu74WqCDkABopP4WfV1qt1Om0Se27KNWYQdPxBgD7APTcf2OBb3QZH5IpX
5 esGvGcCAfmE9VXmT9z3Kpwaloo1kZ3kdEEdYIH7QWc0mbIlMLghgvjfYy43LupoG
6 GD9Hlhvtpynhrc+VE+R3DKKboA8NnT//NuekPkiVdp5qVM7uKNLCiYrW2iKHZDiA
7 mRCbmWmLAC9YPou9mEu0wJxk+MULXjIjgls8IdCcNdcEJO6sRyzPOgBv/6WipGxq
8 15xYJViBUVl8W33JdkGWFTrlodJs49X7/AjHw55GqCixONrPzhzycsgFo8FOCROI
9 BqPHD5N/itGtMu61JGCmvBuXyhUYd9xiBrinalVOxJV+XUJWLGw7KurNQrPa/RwU
10 m9E0cSxwyYWEalpr0fTMpvo2NYcKmJLs30jj9G/Kpqs/7LWjrp7Tm/stHFSpa4Jm
11 Qt1nX7x8Vjt1cnMup0f/dK8eMsx4JsF0YqyklYObyJdJhe1akoz2YhSnD4CNE0T+
12 oIoxrU74w6iK0PF33+w7sc2ZRODZdJcA09r9yZfh68yhGPkcp91koaZso+0uHlHw
13 sN204cy1jhS2s7EJ/J8abHdOnznEw1g/1YIPkhfgEh3ccpGCWPbpAHc12eth+fEl
14 SL5rmFrQtowic2lOYOabWbkP+ZDd5deSlTouOB/iYtsRZP7UINBlqcoYvThx40ba
15 yHKeFE1pitNB3oh3AVGGu8xbzObzjVC32s8caMZqr2QwIyk18oIGQPD4rhcbkRQ8
16 WIeog03dLVEBa+qhgaOZX7zJrYX6eilRGBXmjZueV57VOl3pTQCnpg==
17 -----END RSA PRIVATE KEY-----
+0
-13
test/client_certs/server_cert.crt less more
0 -----BEGIN CERTIFICATE-----
1 MIICAzCCAWwCCQDcY7oXL2AdXTANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJV
2 UzELMAkGA1UECBMCVkExFDASBgNVBAoTC0V2ZW50U291cmNlMRYwFAYDVQQDEw1F
3 dmVudFNvdXJjZUNBMB4XDTE2MDIyOTIwMTQyMVoXDTI2MDIyNjIwMTQyMVowRDEL
4 MAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRQwEgYDVQQKEwtFdmVudFNvdXJjZTES
5 MBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ
6 5BXHRbLlvlMGg19SQ1Bg4iDA8Tt9IJ4P/tocgwamQyCjFpngOi+uDmnXLZFf1x7P
7 ueXEtKVLLGlehcqM3LNS3Z4SUUc+OkcO2ztFZHjWell7FOuDTUuus3BjcFQDDNhd
8 GBNBKI79/oxRVjRFcDdMvTWG0r1UIALvlECTj8uwswIDAQABMA0GCSqGSIb3DQEB
9 BQUAA4GBAFqvIsJWnsV/drGNeuftEMG/zwD+5j8Xe9xCUIewMH5Er20/MXK0owLi
10 V3XI84LpVKi9hfUwJji91EW6Qi18Z4LKdA/bXvLdWwtZMCybYTTGKnLmUELhqIyn
11 VZbgEXyYpiUzRUnIotjbOwQIpP1aj+8Gys6DrHgBEbqrMuI6tiKF
12 -----END CERTIFICATE-----
+0
-18
test/client_certs/server_key.pem less more
0 -----BEGIN RSA PRIVATE KEY-----
1 Proc-Type: 4,ENCRYPTED
2 DEK-Info: DES-EDE3-CBC,5A4FE8B32AF89EBF
3
4 Falz9rSy6LdpFlmXQKkmIGVzYqkmKJ8rA1E/xt5YFOGk7tO6kwCKm5/wOrWv3TrH
5 6v90CTNNJHerwFe7QinEAMiwKaLssR+YUxdNplJrYCbTTRrOo/DER0qVO8bw4yht
6 MawMDY1+pI1YyDpkwNt8QsVn80DFUBTqnXb2A+u0Pk+PaL/hji7t1piGD+yRkPsC
7 Fbx54F3IzZByFyhMQ2YoTzT8OHEyMDEzqxjla7DsWC9PGuFTtp7h6NWA4kT1FBb5
8 kkEIYai/DuN/ng750+7eAVv6K3Fz+byb9t4VMpb3FHpreqk32D8StCVG1N1vUVK7
9 gN8D3X1GBDRKmOEP/hSJOoDZj8W9UXq4SQ9GzRtyVGq2ARMr32P/e/EOq5L4tSy1
10 WVJk0pBVIIUrY2Z0UO5tpK7+pkZvjOCWr68qnXIWcyEptyPqEiFZNqoztRbtaHyf
11 7m8FEDXSRBKQpFyi5p9AWut1hlaf6YyKbw3z8Gqfd1nqbzcqqH2jSN7WdZcJj0Ma
12 JWTMaFBT1wZYQ/mQleLk4TakQf+X/wlq/B9gfrEWR0Zkmc7tuXwDaMU8muQdXx6d
13 Olu73ICqrsajrmILX2tmJo2HsSvfNjxOXC/VORqVwD+Hp09p3UZnrxxNohCm8Qka
14 Dgghd+oU0o1RfdBa+c5ZL6l41ghk2a3zMi/GCGl+KprmMonlRIfUSkMc3tdRQiZV
15 GubJSwASXFxVDrIb64fDdyEryHFxKjyFeHOc9fFyP11TawLJgCKPaiqSnUivvvPr
16 PBei3pkaFiq9mpF3pF3GO7I6ENGpBmU0O/6rVh7hYtg=
17 -----END RSA PRIVATE KEY-----
+0
-1234
test/eventsource_test.js less more
0 /* eslint-disable no-new */
1 var EventSource = require('../lib/eventsource')
2 var bufferFrom = require('buffer-from')
3 var path = require('path')
4 var http = require('http')
5 var https = require('https')
6 var fs = require('fs')
7 var mocha = require('mocha')
8 var assert = require('assert')
9 var u = require('url')
10
11 var it = mocha.it
12 var describe = mocha.describe
13
14 var httpsServerOptions = {
15 key: fs.readFileSync(path.join(__dirname, 'server_certs', 'key.pem')),
16 cert: fs.readFileSync(path.join(__dirname, 'server_certs', 'certificate.pem'))
17 }
18
19 var _port = 20000
20 var servers = []
21 process.on('exit', function () {
22 if (servers.length > 0) {
23 console.error("************ Didn't kill all servers - there is still %d running.", servers.length)
24 }
25 })
26
27 function createServer (callback) {
28 var server = http.createServer()
29 configureServer(server, 'http', _port++, callback)
30 }
31
32 function createHttpsServer (callback) {
33 var server = https.createServer(httpsServerOptions)
34 configureServer(server, 'https', _port++, callback)
35 }
36
37 function createHttpsServerWithClientAuth (callback) {
38 var options = {
39 key: fs.readFileSync(path.join(__dirname, 'client_certs', 'server_key.pem')),
40 cert: fs.readFileSync(path.join(__dirname, 'client_certs', 'server_cert.crt')),
41 ca: fs.readFileSync(path.join(__dirname, 'client_certs', 'cacert.crt')),
42 passphrase: 'test1234$',
43 requestCert: true,
44 rejectAuthorized: true
45 }
46 var server = https.createServer(options)
47 configureServer(server, 'https', _port++, callback)
48 }
49
50 function configureServer (server, protocol, port, callback) {
51 var responses = []
52
53 var oldClose = server.close
54 server.close = function (closeCb) {
55 responses.forEach(function (res) {
56 res.end()
57 })
58 oldClose.call(this, function () {
59 servers.splice(servers.indexOf(server), 1)
60 closeCb()
61 })
62 }
63
64 server.on('request', function (req, res) {
65 responses.push(res)
66 })
67
68 server.url = protocol + '://localhost:' + port
69
70 server.listen(port, function onOpen (err) {
71 servers.push(server)
72 callback(err, server)
73 })
74 }
75
76 function createProxy (target, protocol, callback) {
77 var proxyPort = _port++
78 var targetProtocol = target.indexOf('https') === 0 ? 'https' : 'http'
79 var requester = targetProtocol === 'https' ? https : http
80 var serve = protocol === 'https' ? https : http
81
82 var proxied = []
83 var server = serve.createServer(serve === https ? httpsServerOptions : undefined)
84
85 server.on('request', function (req, res) {
86 var options = u.parse(target)
87 options.headers = req.headers
88 options.rejectUnauthorized = false
89
90 var upstreamReq = requester.request(options, function (upstreamRes) {
91 upstreamRes.pipe(res)
92 })
93
94 proxied.push(upstreamReq)
95 upstreamReq.end()
96 })
97
98 servers.push(server)
99
100 var oldClose = server.close
101 server.close = function (closeCb) {
102 proxied.forEach(function (res) {
103 res.abort()
104 })
105
106 oldClose.call(server, function () {
107 servers.splice(servers.indexOf(server), 1)
108 closeCb()
109 })
110 }
111
112 server.listen(proxyPort, function onOpen (err) {
113 server.url = protocol + '://localhost:' + proxyPort
114 callback(err, server)
115 })
116 }
117
118 function writeEvents (chunks) {
119 return function (req, res) {
120 res.writeHead(200, {'Content-Type': 'text/event-stream'})
121 chunks.forEach(function (chunk) {
122 res.write(chunk)
123 })
124 res.write(':') // send a dummy comment to ensure that the head is flushed
125 }
126 }
127
128 describe('Parser', function () {
129 it('parses multibyte characters', function (done) {
130 createServer(function (err, server) {
131 if (err) return done(err)
132
133 server.on('request', writeEvents(['id: 1\ndata: €豆腐\n\n']))
134 var es = new EventSource(server.url)
135
136 es.onmessage = function (m) {
137 assert.equal('€豆腐', m.data)
138 server.close(done)
139 }
140 })
141 })
142
143 it('parses empty lines with multibyte characters', function (done) {
144 createServer(function (err, server) {
145 if (err) return done(err)
146
147 server.on('request', writeEvents(['\n\n\n\nid: 1\ndata: 我現在都看實況不玩遊戲\n\n']))
148 var es = new EventSource(server.url)
149
150 es.onmessage = function (m) {
151 assert.equal('我現在都看實況不玩遊戲', m.data)
152 server.close(done)
153 }
154 })
155 })
156
157 it('parses one one-line message in one chunk', function (done) {
158 createServer(function (err, server) {
159 if (err) return done(err)
160
161 server.on('request', writeEvents(['data: Hello\n\n']))
162 var es = new EventSource(server.url)
163 es.onmessage = function (m) {
164 assert.equal('Hello', m.data)
165 server.close(done)
166 }
167 })
168 })
169
170 it('ignores byte-order mark', function (done) {
171 createServer(function (err, server) {
172 if (err) return done(err)
173
174 server.on('request', function (req, res) {
175 res.writeHead(200, {'Content-Type': 'text/event-stream'})
176 res.write('\uFEFF')
177 res.write('data: foo\n\n')
178 res.end()
179 })
180 var es = new EventSource(server.url)
181 es.onmessage = function (m) {
182 assert.equal('foo', m.data)
183 server.close(done)
184 }
185 })
186 })
187
188 it('parses one one-line message in two chunks', function (done) {
189 createServer(function (err, server) {
190 if (err) return done(err)
191
192 server.on('request', writeEvents(['data: Hel', 'lo\n\n']))
193 var es = new EventSource(server.url)
194 es.onmessage = function (m) {
195 assert.equal('Hello', m.data)
196 server.close(done)
197 }
198 })
199 })
200
201 it('parses two one-line messages in one chunk', function (done) {
202 createServer(function (err, server) {
203 if (err) return done(err)
204
205 server.on('request', writeEvents(['data: Hello\n\n', 'data: World\n\n']))
206 var es = new EventSource(server.url)
207
208 es.onmessage = first
209
210 function first (m) {
211 assert.equal('Hello', m.data)
212 es.onmessage = second
213 }
214
215 function second (m) {
216 assert.equal('World', m.data)
217 server.close(done)
218 }
219 })
220 })
221
222 it('parses one two-line message in one chunk', function (done) {
223 createServer(function (err, server) {
224 if (err) return done(err)
225
226 server.on('request', writeEvents(['data: Hello\ndata:World\n\n']))
227 var es = new EventSource(server.url)
228
229 es.onmessage = function (m) {
230 assert.equal('Hello\nWorld', m.data)
231 server.close(done)
232 }
233 })
234 })
235
236 it('parses chopped up unicode data', function (done) {
237 createServer(function (err, server) {
238 if (err) return done(err)
239
240 var chopped = 'data: Aslak\n\ndata: Hellesøy\n\n'.split('')
241 server.on('request', writeEvents(chopped))
242 var es = new EventSource(server.url)
243
244 es.onmessage = first
245
246 function first (m) {
247 assert.equal('Aslak', m.data)
248 es.onmessage = second
249 }
250
251 function second (m) {
252 assert.equal('Hellesøy', m.data)
253 server.close(done)
254 }
255 })
256 })
257
258 it('parses really chopped up unicode data', function (done) {
259 createServer(function (err, server) {
260 if (err) return done(err)
261
262 server.on('request', function (req, res) {
263 const msg = bufferFrom('data: Aslak Hellesøy is the original author\n\n')
264 res.writeHead(200, {'Content-Type': 'text/event-stream'})
265
266 // Slice in the middle of a unicode sequence (ø), making sure that one data
267 // chunk will contain the first byte and the second chunk will get the other
268 res.write(msg.slice(0, 19), 'binary', function () {
269 res.write(msg.slice(19))
270 })
271 })
272
273 var es = new EventSource(server.url)
274
275 es.onmessage = function (m) {
276 assert.equal('Aslak Hellesøy is the original author', m.data)
277 server.close(done)
278 }
279 })
280 })
281
282 it('accepts CRLF as separator', function (done) {
283 createServer(function (err, server) {
284 if (err) return done(err)
285
286 var chopped = 'data: Aslak\r\n\r\ndata: Hellesøy\r\n\r\n'.split('')
287 server.on('request', writeEvents(chopped))
288 var es = new EventSource(server.url)
289
290 es.onmessage = first
291
292 function first (m) {
293 assert.equal('Aslak', m.data)
294 es.onmessage = second
295 }
296
297 function second (m) {
298 assert.equal('Hellesøy', m.data)
299 server.close(done)
300 }
301 })
302 })
303
304 it('accepts CR as separator', function (done) {
305 createServer(function (err, server) {
306 if (err) return done(err)
307
308 var chopped = 'data: Aslak\r\rdata: Hellesøy\r\r'.split('')
309 server.on('request', writeEvents(chopped))
310 var es = new EventSource(server.url)
311
312 es.onmessage = first
313
314 function first (m) {
315 assert.equal('Aslak', m.data)
316 es.onmessage = second
317 }
318
319 function second (m) {
320 assert.equal('Hellesøy', m.data)
321 server.close(done)
322 }
323 })
324 })
325
326 it('delivers message with explicit event', function (done) {
327 createServer(function (err, server) {
328 if (err) return done(err)
329
330 server.on('request', writeEvents(['event: greeting\ndata: Hello\n\n']))
331 var es = new EventSource(server.url)
332
333 es.addEventListener('greeting', function (m) {
334 assert.equal('Hello', m.data)
335 server.close(done)
336 })
337 })
338 })
339
340 it('allows removal of event listeners', function (done) {
341 createServer(function (err, server) {
342 if (err) return done(err)
343
344 server.on('request', writeEvents(['event: greeting\ndata: Hello\n\n', 'event: greeting\ndata: World\n\n']))
345 var es = new EventSource(server.url)
346 var numCalled = 0
347
348 function onGreeting (m) {
349 numCalled++
350 assert.equal('Hello', m.data)
351 es.removeEventListener('greeting', onGreeting, false)
352 process.nextTick(scheduleDisconnect)
353 }
354
355 function scheduleDisconnect () {
356 assert.equal(1, numCalled)
357 server.close(done)
358 }
359
360 es.addEventListener('greeting', onGreeting, false)
361 })
362 })
363
364 it('ignores comments', function (done) {
365 createServer(function (err, server) {
366 if (err) return done(err)
367
368 server.on('request', writeEvents(['data: Hello\n\n:nothing to see here\n\ndata: World\n\n']))
369 var es = new EventSource(server.url)
370
371 es.onmessage = first
372
373 function first (m) {
374 assert.equal('Hello', m.data)
375 es.onmessage = second
376 }
377
378 function second (m) {
379 assert.equal('World', m.data)
380 server.close(done)
381 }
382 })
383 })
384
385 it('ignores empty comments', function (done) {
386 createServer(function (err, server) {
387 if (err) return done(err)
388
389 server.on('request', writeEvents(['data: Hello\n\n:\n\ndata: World\n\n']))
390 var es = new EventSource(server.url)
391
392 es.onmessage = first
393
394 function first (m) {
395 assert.equal('Hello', m.data)
396 es.onmessage = second
397 }
398
399 function second (m) {
400 assert.equal('World', m.data)
401 server.close(done)
402 }
403 })
404 })
405
406 it('does not ignore multilines strings', function (done) {
407 createServer(function (err, server) {
408 if (err) return done(err)
409
410 server.on('request', writeEvents(['data: line one\ndata:\ndata: line two\n\n']))
411 var es = new EventSource(server.url)
412
413 es.onmessage = function (m) {
414 assert.equal('line one\n\nline two', m.data)
415 server.close(done)
416 }
417 })
418 })
419
420 it('does not ignore multilines strings even in data beginning', function (done) {
421 createServer(function (err, server) {
422 if (err) return done(err)
423
424 server.on('request', writeEvents(['data:\ndata:line one\ndata: line two\n\n']))
425 var es = new EventSource(server.url)
426
427 es.onmessage = function (m) {
428 assert.equal('\nline one\nline two', m.data)
429 server.close(done)
430 }
431 })
432 })
433
434 it('causes entire event to be ignored for empty event field', function (done) {
435 createServer(function (err, server) {
436 if (err) return done(err)
437
438 server.on('request', writeEvents(['event:\n\ndata: Hello\n\n']))
439 var es = new EventSource(server.url)
440
441 var originalEmit = es.emit
442 es.emit = function (event) {
443 assert.ok(event === 'message' || event === 'newListener')
444 return originalEmit.apply(this, arguments)
445 }
446 es.onmessage = function (m) {
447 assert.equal('Hello', m.data)
448 server.close(done)
449 }
450 })
451 })
452
453 it('parses relatively huge messages efficiently', function (done) {
454 this.timeout(1000)
455
456 createServer(function (err, server) {
457 if (err) return done(err)
458 var longMessage = 'data: ' + new Array(100000).join('a') + '\n\n'
459 server.on('request', writeEvents([longMessage]))
460
461 var es = new EventSource(server.url)
462
463 es.onmessage = function () {
464 server.close(done)
465 }
466 })
467 })
468 })
469
470 describe('HTTP Request', function () {
471 it('passes cache-control: no-cache to server', function (done) {
472 createServer(function (err, server) {
473 if (err) return done(err)
474
475 server.on('request', function (req) {
476 assert.equal('no-cache', req.headers['cache-control'])
477 server.close(done)
478 })
479
480 EventSource(server.url)
481 })
482 })
483
484 it('sets request headers', function (done) {
485 createServer(function (err, server) {
486 if (err) return done(err)
487
488 server.on('request', function (req) {
489 assert.equal(req.headers['user-agent'], 'test')
490 assert.equal(req.headers['cookie'], 'test=test')
491 assert.equal(req.headers['last-event-id'], '99')
492 server.close(done)
493 })
494
495 var headers = {
496 'User-Agent': 'test',
497 'Cookie': 'test=test',
498 'Last-Event-ID': '99'
499 }
500 new EventSource(server.url, {headers: headers})
501 })
502 })
503
504 it("does not set request headers that don't have a value", function (done) {
505 createServer(function (err, server) {
506 if (err) return done(err)
507
508 server.on('request', function (req) {
509 assert.equal(req.headers['user-agent'], 'test')
510 assert.equal(req.headers['cookie'], 'test=test')
511 assert.equal(req.headers['last-event-id'], '99')
512 assert.equal(req.headers['X-Something'], undefined)
513 server.close(done)
514 })
515
516 var headers = {
517 'User-Agent': 'test',
518 'Cookie': 'test=test',
519 'Last-Event-ID': '99',
520 'X-Something': null
521 }
522
523 assert.doesNotThrow(
524 function () {
525 new EventSource(server.url, {headers: headers})
526 }
527 )
528 })
529 });
530
531 [301, 307].forEach(function (status) {
532 it('follows http ' + status + ' redirect', function (done) {
533 var redirectSuffix = '/foobar'
534 var clientRequestedRedirectUrl = false
535 createServer(function (err, server) {
536 if (err) return done(err)
537
538 server.on('request', function (req, res) {
539 if (req.url === '/') {
540 res.writeHead(status, {
541 'Connection': 'Close',
542 'Location': server.url + redirectSuffix
543 })
544 res.end()
545 } else if (req.url === redirectSuffix) {
546 clientRequestedRedirectUrl = true
547 res.writeHead(200, {'Content-Type': 'text/event-stream'})
548 res.end()
549 }
550 })
551
552 var es = new EventSource(server.url)
553 es.onopen = function () {
554 assert.ok(clientRequestedRedirectUrl)
555 assert.equal(server.url + redirectSuffix, es.url)
556 server.close(done)
557 }
558 })
559 })
560
561 it('causes error event when response is ' + status + ' with missing location', function (done) {
562 createServer(function (err, server) {
563 if (err) return done(err)
564
565 server.on('request', function (req, res) {
566 res.writeHead(status, 'status message', {
567 'Connection': 'Close'
568 })
569 res.end()
570 })
571
572 var es = new EventSource(server.url)
573 es.onerror = function (err) {
574 assert.equal(err.status, status)
575 assert.equal(err.message, 'status message')
576 server.close(done)
577 }
578 })
579 })
580 });
581
582 [401, 403].forEach(function (status) {
583 it('causes error event when response status is ' + status, function (done) {
584 createServer(function (err, server) {
585 if (err) return done(err)
586
587 server.on('request', function (req, res) {
588 res.writeHead(status, 'status message', {'Content-Type': 'text/html'})
589 res.end()
590 })
591
592 var es = new EventSource(server.url)
593 es.onerror = function (err) {
594 assert.equal(err.status, status)
595 assert.equal(err.message, 'status message')
596 server.close(done)
597 }
598 })
599 })
600 })
601 })
602
603 describe('HTTPS Support', function () {
604 it('uses https for https urls', function (done) {
605 createHttpsServer(function (err, server) {
606 if (err) return done(err)
607
608 server.on('request', writeEvents(['data: hello\n\n']))
609 var es = new EventSource(server.url, {rejectUnauthorized: false})
610
611 es.onmessage = function (m) {
612 assert.equal('hello', m.data)
613 server.close(done)
614 }
615 })
616 })
617 })
618
619 describe('HTTPS Client Certificate Support', function () {
620 it('uses client certificate for https urls', function (done) {
621 this.timeout(1500000)
622 createHttpsServerWithClientAuth(function (err, server) {
623 if (err) return done(err)
624
625 server.on('request', writeEvents(['data: hello\n\n']))
626 var es = new EventSource(server.url,
627 {
628 https: {
629 key: fs.readFileSync(path.join(__dirname, 'client_certs', 'client_key.pem')),
630 cert: fs.readFileSync(path.join(__dirname, 'client_certs', 'client_cert.crt')),
631 ca: fs.readFileSync(path.join(__dirname, 'client_certs', 'cacert.crt')),
632 passphrase: 'test1234$',
633 rejectUnauthorized: true
634 }
635 }
636 )
637 es.onmessage = function (m) {
638 assert.equal('hello', m.data)
639 server.close(done)
640 }
641 })
642 })
643 })
644
645 describe('Reconnection', function () {
646 it('is attempted when server is down', function (done) {
647 var es = new EventSource('http://localhost:' + _port)
648 es.reconnectInterval = 0
649
650 es.onerror = function () {
651 es.onerror = null
652 createServer(function (err, server) {
653 if (err) return done(err)
654
655 server.on('request', writeEvents(['data: hello\n\n']))
656
657 es.onmessage = function (m) {
658 assert.equal('hello', m.data)
659 server.close(done)
660 }
661 })
662 }
663 })
664
665 it('is attempted when server goes down after connection', function (done) {
666 createServer(function (err, server) {
667 if (err) return done(err)
668
669 server.on('request', writeEvents(['data: hello\n\n']))
670 var es = new EventSource(server.url)
671 es.reconnectInterval = 0
672
673 es.onmessage = function (m) {
674 assert.equal('hello', m.data)
675 server.close(function (err) {
676 if (err) return done(err)
677
678 var port = u.parse(es.url).port
679 configureServer(http.createServer(), 'http', port, function (err, server2) {
680 if (err) return done(err)
681
682 server2.on('request', writeEvents(['data: world\n\n']))
683 es.onmessage = function (m) {
684 assert.equal('world', m.data)
685 server2.close(done)
686 }
687 })
688 })
689 }
690 })
691 })
692
693 it('is attempted when the server responds with a 500', function (done) {
694 createServer(function (err, server) {
695 if (err) return done(err)
696
697 server.on('request', function (req, res) {
698 res.writeHead(500)
699 res.end()
700 })
701
702 var es = new EventSource(server.url)
703 es.reconnectInterval = 0
704
705 var errored = false
706
707 es.onerror = function () {
708 if (errored) return
709 errored = true
710 server.close(function (err) {
711 if (err) return done(err)
712
713 var port = u.parse(es.url).port
714 configureServer(http.createServer(), 'http', port, function (err, server2) {
715 if (err) return done(err)
716
717 server2.on('request', writeEvents(['data: hello\n\n']))
718 es.onmessage = function (m) {
719 assert.equal('hello', m.data)
720 server2.close(done)
721 }
722 })
723 })
724 }
725 })
726 })
727
728 it('is stopped when server goes down and eventsource is being closed', function (done) {
729 createServer(function (err, server) {
730 if (err) return done(err)
731
732 server.on('request', writeEvents(['data: hello\n\n']))
733 var es = new EventSource(server.url)
734 es.reconnectInterval = 0
735
736 es.onmessage = function (m) {
737 assert.equal('hello', m.data)
738 server.close(function (err) {
739 if (err) return done(err)
740 // The server has closed down. es.onerror should now get called,
741 // because es's remote connection was dropped.
742 })
743 }
744
745 es.onerror = function () {
746 // We received an error because the remote connection was closed.
747 // We close es, so we do not want es to reconnect.
748 es.close()
749
750 var port = u.parse(es.url).port
751 configureServer(http.createServer(), 'http', port, function (err, server2) {
752 if (err) return done(err)
753 server2.on('request', writeEvents(['data: world\n\n']))
754
755 es.onmessage = function (m) {
756 return done(new Error('Unexpected message: ' + m.data))
757 }
758
759 setTimeout(function () {
760 // We have not received any message within 100ms, we can
761 // presume this works correctly.
762 server2.close(done)
763 }, 100)
764 })
765 }
766 })
767 })
768
769 it('is not attempted when server responds with non-200 and non-500', function (done) {
770 createServer(function (err, server) {
771 if (err) return done(err)
772
773 server.on('request', function (req, res) {
774 res.writeHead(204, 'status message')
775 res.end()
776 })
777
778 var es = new EventSource(server.url)
779 es.reconnectInterval = 0
780
781 es.onerror = function (e) {
782 assert.equal(e.status, 204)
783 assert.equal(e.message, 'status message')
784 server.close(function (err) {
785 if (err) return done(err)
786
787 var port = u.parse(es.url).port
788 configureServer(http.createServer(), 'http', port, function (err, server2) {
789 if (err) return done(err)
790
791 // this will be verified by the readyState
792 // going from CONNECTING to CLOSED,
793 // along with the tests verifying that the
794 // state is CONNECTING when a server closes.
795 // it's next to impossible to write a fail-safe
796 // test for this, though.
797 var ival = setInterval(function () {
798 if (es.readyState === EventSource.CLOSED) {
799 clearInterval(ival)
800 server2.close(done)
801 }
802 }, 5)
803 })
804 })
805 }
806 })
807 })
808
809 it('sends Last-Event-ID http header when it has previously been passed in an event from the server', function (done) {
810 createServer(function (err, server) {
811 if (err) return done(err)
812
813 server.on('request', writeEvents(['id: 10\ndata: Hello\n\n']))
814
815 var es = new EventSource(server.url)
816 es.reconnectInterval = 0
817
818 es.onmessage = function () {
819 server.close(function (err) {
820 if (err) return done(err)
821
822 var port = u.parse(es.url).port
823 configureServer(http.createServer(), 'http', port, function (err, server2) {
824 if (err) return done(err)
825
826 server2.on('request', function (req, res) {
827 assert.equal('10', req.headers['last-event-id'])
828 server2.close(done)
829 })
830 })
831 })
832 }
833 })
834 })
835
836 it('sends correct Last-Event-ID http header when an initial Last-Event-ID header was specified in the constructor', function (done) {
837 createServer(function (err, server) {
838 if (err) return done(err)
839
840 server.on('request', function (req, res) {
841 assert.equal('9', req.headers['last-event-id'])
842 server.close(done)
843 })
844
845 new EventSource(server.url, {headers: {'Last-Event-ID': '9'}})
846 })
847 })
848
849 it('does not send Last-Event-ID http header when it has not been previously sent by the server', function (done) {
850 createServer(function (err, server) {
851 if (err) return done(err)
852
853 server.on('request', writeEvents(['data: Hello\n\n']))
854
855 var es = new EventSource(server.url)
856 es.reconnectInterval = 0
857
858 es.onmessage = function () {
859 server.close(function (err) {
860 if (err) return done(err)
861
862 var port = u.parse(es.url).port
863 configureServer(http.createServer(), 'http', port, function (err, server2) {
864 if (err) return done(err)
865
866 server2.on('request', function (req, res) {
867 assert.equal(undefined, req.headers['last-event-id'])
868 server2.close(done)
869 })
870 })
871 })
872 }
873 })
874 })
875 })
876
877 describe('readyState', function () {
878 it('has CONNECTING constant', function () {
879 assert.equal(0, EventSource.CONNECTING)
880 })
881
882 it('has OPEN constant', function () {
883 assert.equal(1, EventSource.OPEN)
884 })
885
886 it('has CLOSED constant', function () {
887 assert.equal(2, EventSource.CLOSED)
888 })
889
890 it('has readystate constants on instances', function (done) {
891 var es = new EventSource('http://localhost:' + _port)
892 assert.equal(EventSource.CONNECTING, es.CONNECTING, 'constant CONNECTING missing/invalid')
893 assert.equal(EventSource.OPEN, es.OPEN, 'constant OPEN missing/invalid')
894 assert.equal(EventSource.CLOSED, es.CLOSED, 'constant CLOSED missing/invalid')
895
896 es.onerror = function () {
897 es.close()
898 done()
899 }
900 })
901
902 it('is CONNECTING before connection has been established', function (done) {
903 var es = new EventSource('http://localhost:' + _port)
904 assert.equal(EventSource.CONNECTING, es.readyState)
905 es.onerror = function () {
906 es.close()
907 done()
908 }
909 })
910
911 it('is CONNECTING when server has closed the connection', function (done) {
912 createServer(function (err, server) {
913 if (err) return done(err)
914
915 server.on('request', writeEvents([]))
916 var es = new EventSource(server.url)
917 es.reconnectInterval = 0
918
919 es.onopen = function (m) {
920 server.close(function (err) {
921 if (err) return done(err)
922
923 es.onerror = function () {
924 es.onerror = null
925 assert.equal(EventSource.CONNECTING, es.readyState)
926 done()
927 }
928 })
929 }
930 })
931 })
932
933 it('is OPEN when connection has been established', function (done) {
934 createServer(function (err, server) {
935 if (err) return done(err)
936
937 server.on('request', writeEvents([]))
938 var es = new EventSource(server.url)
939
940 es.onopen = function () {
941 assert.equal(EventSource.OPEN, es.readyState)
942 server.close(done)
943 }
944 })
945 })
946
947 it('is CLOSED after connection has been closed', function (done) {
948 createServer(function (err, server) {
949 if (err) return done(err)
950
951 server.on('request', writeEvents([]))
952 var es = new EventSource(server.url)
953
954 es.onopen = function () {
955 es.close()
956 assert.equal(EventSource.CLOSED, es.readyState)
957 server.close(done)
958 }
959 })
960 })
961 })
962
963 describe('Methods', function () {
964 it('close method exists and can be called to close an eventsource', function (done) {
965 createServer(function (err, server) {
966 if (err) return done(err)
967 var es = new EventSource(server.url)
968 server.on('request', writeEvents([]))
969 es.onopen = function () {
970 assert.equal(es.close(), undefined)
971 server.close(done)
972 }
973 })
974 })
975
976 it('close method is a prototype method', function () {
977 assert.equal(typeof EventSource.prototype.close, 'function')
978 })
979 })
980
981 describe('Properties', function () {
982 it('url exposes original request url', function () {
983 var url = 'http://localhost:' + _port
984 var es = new EventSource(url)
985 assert.equal(url, es.url)
986 })
987 })
988
989 describe('Events', function () {
990 it('calls onopen when connection is established', function (done) {
991 createServer(function (err, server) {
992 if (err) return done(err)
993
994 server.on('request', writeEvents([]))
995 var es = new EventSource(server.url)
996
997 es.onopen = function (event) {
998 assert.equal(event.type, 'open')
999 server.close(done)
1000 }
1001 })
1002 })
1003
1004 it('supplies the correct origin', function (done) {
1005 createServer(function (err, server) {
1006 if (err) return done(err)
1007
1008 server.on('request', writeEvents(['data: hello\n\n']))
1009 var es = new EventSource(server.url)
1010
1011 es.onmessage = function (event) {
1012 assert.equal(event.origin, server.url)
1013 server.close(done)
1014 }
1015 })
1016 })
1017
1018 it('emits open event when connection is established', function (done) {
1019 createServer(function (err, server) {
1020 if (err) return done(err)
1021
1022 server.on('request', writeEvents([]))
1023 var es = new EventSource(server.url)
1024
1025 es.addEventListener('open', function (event) {
1026 assert.equal(event.type, 'open')
1027 server.close(done)
1028 })
1029 })
1030 })
1031
1032 it('does not double reconnect when connection is closed by server', function (done) {
1033 createServer(function (err, server) {
1034 if (err) return done(err)
1035
1036 var numConnections = 0
1037 server.on('request', function (req, res) {
1038 numConnections++
1039 writeEvents([])(req, res)
1040
1041 if (numConnections > 2) done(new Error('reopening too many connections'))
1042 // destroy only the first connection - expected only 1 other reconnect
1043 if (numConnections === 1) {
1044 process.nextTick(function () {
1045 req.destroy()
1046 })
1047 }
1048 })
1049 const es = new EventSource(server.url)
1050 es.reconnectInterval = 50
1051
1052 setTimeout(function () {
1053 server.close(done)
1054 }, 350)
1055 })
1056 })
1057
1058 it('does not emit error when connection is closed by client', function (done) {
1059 createServer(function (err, server) {
1060 if (err) return done(err)
1061
1062 server.on('request', writeEvents([]))
1063 var es = new EventSource(server.url)
1064
1065 es.addEventListener('open', function () {
1066 es.close()
1067 process.nextTick(function () {
1068 server.close(done)
1069 })
1070 })
1071 es.addEventListener('error', function () {
1072 done(new Error('error should not be emitted'))
1073 })
1074 })
1075 })
1076
1077 it('populates message\'s lastEventId correctly when the last event has an associated id', function (done) {
1078 createServer(function (err, server) {
1079 if (err) return done(err)
1080
1081 server.on('request', writeEvents(['id: 123\ndata: hello\n\n']))
1082 var es = new EventSource(server.url)
1083
1084 es.onmessage = function (m) {
1085 assert.equal(m.lastEventId, '123')
1086 server.close(done)
1087 }
1088 })
1089 })
1090
1091 it('populates message\'s lastEventId correctly when the last event doesn\'t have an associated id', function (done) {
1092 createServer(function (err, server) {
1093 if (err) return done(err)
1094
1095 server.on('request', writeEvents(['id: 123\ndata: Hello\n\n', 'data: World\n\n']))
1096 var es = new EventSource(server.url)
1097
1098 es.onmessage = first
1099
1100 function first () {
1101 es.onmessage = second
1102 }
1103
1104 function second (m) {
1105 assert.equal(m.data, 'World')
1106 assert.equal(m.lastEventId, '123') // expect to get back the previous event id
1107 server.close(done)
1108 }
1109 })
1110 })
1111
1112 it('populates messages with enumerable properties so they can be inspected via console.log().', function (done) {
1113 createServer(function (err, server) {
1114 if (err) return done(err)
1115
1116 server.on('request', writeEvents(['data: World\n\n']))
1117 var es = new EventSource(server.url)
1118
1119 es.onmessage = function (m) {
1120 var enumerableAttributes = Object.keys(m)
1121 assert.notEqual(enumerableAttributes.indexOf('data'), -1)
1122 assert.notEqual(enumerableAttributes.indexOf('type'), -1)
1123 server.close(done)
1124 }
1125 })
1126 })
1127
1128 it('throws error if the message type is unspecified, \'\' or null', function (done) {
1129 createServer(function (err, server) {
1130 if (err) return done(err)
1131
1132 var es = new EventSource(server.url)
1133
1134 assert.throws(function () { es.dispatchEvent({}) })
1135 assert.throws(function () { es.dispatchEvent({type: undefined}) })
1136 assert.throws(function () { es.dispatchEvent({type: ''}) })
1137 assert.throws(function () { es.dispatchEvent({type: null}) })
1138
1139 server.close(done)
1140 })
1141 })
1142
1143 it('delivers the dispatched event without payload', function (done) {
1144 createServer(function (err, server) {
1145 if (err) return done(err)
1146
1147 var es = new EventSource(server.url)
1148
1149 es.addEventListener('greeting', function (m) {
1150 server.close(done)
1151 })
1152
1153 es.dispatchEvent({type: 'greeting'})
1154 })
1155 })
1156
1157 it('delivers the dispatched event with payload', function (done) {
1158 createServer(function (err, server) {
1159 if (err) return done(err)
1160
1161 var es = new EventSource(server.url)
1162
1163 es.addEventListener('greeting', function (m) {
1164 assert.equal('Hello', m.data)
1165 server.close(done)
1166 })
1167
1168 es.dispatchEvent({type: 'greeting', detail: {data: 'Hello'}})
1169 })
1170 })
1171 })
1172
1173 describe('Proxying', function () {
1174 it('proxies http->http requests', function (done) {
1175 createServer(function (err, server) {
1176 if (err) return done(err)
1177
1178 server.on('request', writeEvents(['data: World\n\n']))
1179
1180 createProxy(server.url, 'http', function (err, proxy) {
1181 if (err) return done(err)
1182
1183 var es = new EventSource(server.url, {proxy: proxy.url})
1184 es.onmessage = function (m) {
1185 assert.equal(m.data, 'World')
1186 proxy.close(function () {
1187 server.close(done)
1188 })
1189 }
1190 })
1191 })
1192 })
1193
1194 it('proxies http->https requests', function (done) {
1195 createHttpsServer(function (err, server) {
1196 if (err) return done(err)
1197
1198 server.on('request', writeEvents(['data: World\n\n']))
1199
1200 createProxy(server.url, 'http', function (err, proxy) {
1201 if (err) return done(err)
1202
1203 var es = new EventSource(server.url, {proxy: proxy.url})
1204 es.onmessage = function (m) {
1205 assert.equal(m.data, 'World')
1206 proxy.close(function () {
1207 server.close(done)
1208 })
1209 }
1210 })
1211 })
1212 })
1213
1214 it('proxies https->http requests', function (done) {
1215 createHttpsServer(function (err, server) {
1216 if (err) return done(err)
1217
1218 server.on('request', writeEvents(['data: World\n\n']))
1219
1220 createProxy(server.url, 'https', function (err, proxy) {
1221 if (err) return done(err)
1222
1223 var es = new EventSource(server.url, {proxy: proxy.url, rejectUnauthorized: false})
1224 es.onmessage = function (m) {
1225 assert.equal(m.data, 'World')
1226 proxy.close(function () {
1227 server.close(done)
1228 })
1229 }
1230 })
1231 })
1232 })
1233 })
+0
-13
test/server_certs/certificate.pem less more
0 -----BEGIN CERTIFICATE-----
1 MIICATCCAWoCCQDPufXH86n2QzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJu
2 bzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
3 cyBQdHkgTHRkMB4XDTEyMDEwMTE0NDQwMFoXDTIwMDMxOTE0NDQwMFowRTELMAkG
4 A1UEBhMCbm8xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
5 IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrQ7
6 +r//2iV/B6F+4boH0XqFn7alcV9lpjvAmwRXNKnxAoa0f97AjYPGNLKrjpkNXXhB
7 JROIdbRbZnCNeC5fzX1a+JCo7KStzBXuGSZr27TtFmcV4H+9gIRIcNHtZmJLnxbJ
8 sIhkGR8yVYdmJZe4eT5ldk1zoB1adgPF1hZhCBMCAwEAATANBgkqhkiG9w0BAQUF
9 AAOBgQCeWBEHYJ4mCB5McwSSUox0T+/mJ4W48L/ZUE4LtRhHasU9hiW92xZkTa7E
10 QLcoJKQiWfiLX2ysAro0NX4+V8iqLziMqvswnPzz5nezaOLE/9U/QvH3l8qqNkXu
11 rNbsW1h/IO6FV8avWFYVFoutUwOaZ809k7iMh2F2JMgXQ5EymQ==
12 -----END CERTIFICATE-----
+0
-15
test/server_certs/key.pem less more
0 -----BEGIN RSA PRIVATE KEY-----
1 MIICXAIBAAKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEChrR/
2 3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0WZxXg
3 f72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwIDAQAB
4 AoGAAlVY8sHi/aE+9xT77twWX3mGHV0SzdjfDnly40fx6S1Gc7bOtVdd9DC7pk6l
5 3ENeJVR02IlgU8iC5lMHq4JEHPE272jtPrLlrpWLTGmHEqoVFv9AITPqUDLhB9Kk
6 Hjl7h8NYBKbr2JHKICr3DIPKOT+RnXVb1PD4EORbJ3ooYmkCQQDfknUnVxPgxUGs
7 ouABw1WJIOVgcCY/IFt4Ihf6VWTsxBgzTJKxn3HtgvE0oqTH7V480XoH0QxHhjLq
8 DrgobWU9AkEA0TRJ8/ouXGnFEPAXjWr9GdPQRZ1Use2MrFjneH2+Sxc0CmYtwwqL
9 Kr5kS6mqJrxprJeluSjBd+3/ElxURrEXjwJAUvmlN1OPEhXDmRHd92mKnlkyKEeX
10 OkiFCiIFKih1S5Y/sRJTQ0781nyJjtJqO7UyC3pnQu1oFEePL+UEniRztQJAMfav
11 AtnpYKDSM+1jcp7uu9BemYGtzKDTTAYfoiNF42EzSJiGrWJDQn4eLgPjY0T0aAf/
12 yGz3Z9ErbhMm/Ysl+QJBAL4kBxRT8gM4ByJw4sdOvSeCCANFq8fhbgm8pGWlCPb5
13 JGmX3/GHFM8x2tbWMGpyZP1DLtiNEFz7eCGktWK5rqE=
14 -----END RSA PRIVATE KEY-----