btford / btford/angular-socket-io
Require a method to update inner ioSocket object for connect / disconnect
- Dominant language
- JavaScript
- Stars
- 1.5k
- Forks
- 225
- PR merge metrics
- No merged PRs in 30d
Description
In my app, I have both traditional http and websockets -- both are protected by JSON web token authentication. When a user logs in (i.e. post to http endpoint), a token is returned, and then the client will attempt to connect to the websocket endpoint with the token. The connection is rejected if the token isn't valid.
When a user logs out, the websocket is disconnected. I don't want to leave that channel open anymore b/c the user is no longer authenticated. Likewise, I don't want to re-use that same websocket if a new user logs in, b/c the authentication token will be different (and not valid for the new user).
What I'm left with is something like this:
``` javascript
angular.module('app.security')
.factory('Socket', ['socketFactory', '$rootScope', function (socketFactory, $rootScope) {
var socket, token = /* get token */
function connect(token) {
socket = io.connect('', { query: 'token=' + token, forceNew: true });
socket.on('connect', function () { /* etc. */ });
// other event handling
}
// connect if we have a token
if (token) { connect(token); }
$rootScope.on('login', function ( ) {
token = /* get token */
connect(token);
});
$rootScope.on('logout', function () { socket.disconnect(); })
return socketFactory({ ioSocket: socket });
}]);
```
..and this is an example of how it is in injected into a controller to be used...
``` javascript
angular.module('app.something')
.controller('FooCtrl', ['Socket', '$scope', function (Socket, $scope) {
Socket.forward('time:request', $scope);
$scope.$on('socket:time:response', function (evt, data) {
console.log('the current time is ', data);
});
Socket.emit('time:request');
}]);
```
On login, the websocket is connected. On logout it is disconnected, and at the end, it is returning the `socketFactory` wrapper.
The problem here is that `socketFactory.$get` is only ever called once in the provider, which means that the very first time `Socket` is injected into a controller it is valid and connected. But if a user logs out and logs in again, angular re-injects the same instance into a controller, and the internal `ioSocket` has since been disconnected and is no longer good. (note the use of socket.io `forceNew` option which abandons the socket wholesale and initiates a brand new connection).
What is needed is something like the angular [service recipe](https://docs.angularjs.org/guide/providers#service-recipe) pattern which news up the object each time, so we don't re-use the same instance of the wrapper...either that or else an API exposed on socketFactory itself that allows one to replace the inner `ioSocket` reference.
Any ideas on the best way to accomplish this?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.