/
server.js
77 lines (69 loc) · 2.22 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
'use strict';
const http = require('http');
const url = require('url');
const ws = require('ws');
/**
* Minimum viable WebSocket server for Node.js that works through the Primus
* interface.
*
* @runat server
* @api private
*/
module.exports = function server() {
this.service = new ws.Server(Object.assign({
perMessageDeflate: !!this.primus.options.compression,
maxPayload: this.primus.options.maxLength
}, this.primus.options.transport, {
clientTracking: false,
noServer: true
}));
/**
* Noop! Pointless, empty function that will actually be really useful.
*
* @param {Error} err We failed at something.
* @api private
*/
const noop = (err) => err && this.logger.error(err);
//
// Listen to upgrade requests.
//
this.on('upgrade', (req, socket, head) => {
this.service.handleUpgrade(req, socket, head, (socket) => {
const spark = new this.Spark(
req.headers // HTTP request headers.
, req // IP address location.
, url.parse(req.url).query // Optional query string.
, null // We don't have an unique id.
, req // Reference to the HTTP req.
, socket // Reference to the WebSocket.
);
spark.on('outgoing::end', () => socket && socket.close());
spark.on('outgoing::data', (data) => {
if (socket.readyState !== socket.OPEN) return;
socket.send(data, noop);
});
socket.on('message',
spark.emits('incoming::data', (next, data, isBinary) => {
next(undefined, isBinary === false ? data.toString() : data);
})
);
socket.on('error', spark.emits('incoming::error'));
socket.on('ping', spark.emits('incoming::pong', (next) => {
next(undefined, null);
}));
socket.on('close', spark.emits('incoming::end', (next) => {
socket.removeAllListeners();
socket = null;
next();
}));
});
});
//
// Listen to non-upgrade requests.
//
this.on('request', (req, res) => {
res.writeHead(426, { 'content-type': 'text/plain' });
res.end(http.STATUS_CODES[426]);
});
this.once('close', () => this.service.close());
};