General overview of the code:
I'm trying to merge Express and Socket.IO session management using Redis. Seems to work thus far, but I'm having trouble trapping errors using domains as seen in the test below.
Server code:
"use strict";
var domain = require("domain");
var redis = require("redis");
var express = require("express");
var app = express();
var server = require("http").createServer(app);
var socketio = require("socket.io");
var redisSio = require("socket.io-redis");
// Configure Express:
app.use(require("compression")());
app.use(require("body-parser").json());
var expressSession = require("express-session");
// Configure Socket.IO:
app.io = socketio(server, {
transports: ["websocket", "polling"],
// Same name as Express cookie:
cookie: "test.sid"
});
// Manage Socket.IO sessions using Redis:
app.io.adapter(redisSio({socket: "/tmp/redis.sock"}));
// Manage Express sessions using Redis:
app.use(expressSession({
// Same name as Socket.IO cookie:
name: "test.sid",
resave: false,
saveUninitialized: false,
secret: "secret",
store: redis.createClient("/tmp/redis.sock", {
return_buffers: true
})
}));
var d = domain.create();
d.on("error", function(err) { console.log("Error"); });
d.run(function() {
// Configure listener for Socket.IO connections:
app.io.on("connection", d.bind(function(socket) {
// Configure listener for specific event:
socket.on("channel", d.bind(function(data, callback) {
// "data" is general data incoming from client.
// "callback" is a client function meant for acknowledgments.
// Generate an error:
null.test();
}));
}));
});
// Start the server:
server.listen(8080);
Client code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test</title>
<script language="javascript" type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var sock = io.connect();
if(sock) {
sock.emit("channel", null, function(data) {
$("#tester").text(JSON.stringify(data));
});
}
if(sock) {
sock.disconnect();
sock = null;
}
</script>
</head>
<body>
<p id="tester"></p>
</body>
</html>
When receiving the event from the client (triggering the error), the following is printed to the console:
Missing error handler on `socket`.
TypeError: Cannot call method 'test' of null
at Socket.<anonymous> (/home/debian/test.js:46:12)
at Socket.b (domain.js:183:18)
at Socket.emit (events.js:98:17)
at Socket.onevent (/home/debian/node_modules/socket.io/lib/socket.js:330:8)
at Socket.onpacket (/home/debian/node_modules/socket.io/lib/socket.js:290:12)
at Client.ondecoded (/home/debian/node_modules/socket.io/lib/client.js:193:14)
at Decoder.Emitter.emit (/home/debian/node_modules/socket.io/node_modules/socket.io-parser/node_modules/component-emitter/index.js:134:20)
at Decoder.add (/home/debian/node_modules/socket.io/node_modules/socket.io-parser/index.js:247:12)
at Client.ondata (/home/debian/node_modules/socket.io/lib/client.js:175:18)
at Socket.emit (events.js:95:17)
Why isn't the domain catching the error? And why is it complaining about a missing error handler on socket
?
Relevant package versions:
- Node.js (v0.10.38) and also io.js (v2.5.0)
- Express (4.13.3)
- Socket.IO (1.3.6)