websocket.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. 'use strict';
  2. var utils = require('../utils/event')
  3. , urlUtils = require('../utils/url')
  4. , inherits = require('inherits')
  5. , EventEmitter = require('events').EventEmitter
  6. , WebsocketDriver = require('./driver/websocket')
  7. ;
  8. var debug = function() {};
  9. if (process.env.NODE_ENV !== 'production') {
  10. debug = require('debug')('sockjs-client:websocket');
  11. }
  12. function WebSocketTransport(transUrl, ignore, options) {
  13. if (!WebSocketTransport.enabled()) {
  14. throw new Error('Transport created when disabled');
  15. }
  16. EventEmitter.call(this);
  17. debug('constructor', transUrl);
  18. var self = this;
  19. var url = urlUtils.addPath(transUrl, '/websocket');
  20. if (url.slice(0, 5) === 'https') {
  21. url = 'wss' + url.slice(5);
  22. } else {
  23. url = 'ws' + url.slice(4);
  24. }
  25. this.url = url;
  26. this.ws = new WebsocketDriver(this.url, [], options);
  27. this.ws.onmessage = function(e) {
  28. debug('message event', e.data);
  29. self.emit('message', e.data);
  30. };
  31. // Firefox has an interesting bug. If a websocket connection is
  32. // created after onunload, it stays alive even when user
  33. // navigates away from the page. In such situation let's lie -
  34. // let's not open the ws connection at all. See:
  35. // https://github.com/sockjs/sockjs-client/issues/28
  36. // https://bugzilla.mozilla.org/show_bug.cgi?id=696085
  37. this.unloadRef = utils.unloadAdd(function() {
  38. debug('unload');
  39. self.ws.close();
  40. });
  41. this.ws.onclose = function(e) {
  42. debug('close event', e.code, e.reason);
  43. self.emit('close', e.code, e.reason);
  44. self._cleanup();
  45. };
  46. this.ws.onerror = function(e) {
  47. debug('error event', e);
  48. self.emit('close', 1006, 'WebSocket connection broken');
  49. self._cleanup();
  50. };
  51. }
  52. inherits(WebSocketTransport, EventEmitter);
  53. WebSocketTransport.prototype.send = function(data) {
  54. var msg = '[' + data + ']';
  55. debug('send', msg);
  56. this.ws.send(msg);
  57. };
  58. WebSocketTransport.prototype.close = function() {
  59. debug('close');
  60. var ws = this.ws;
  61. this._cleanup();
  62. if (ws) {
  63. ws.close();
  64. }
  65. };
  66. WebSocketTransport.prototype._cleanup = function() {
  67. debug('_cleanup');
  68. var ws = this.ws;
  69. if (ws) {
  70. ws.onmessage = ws.onclose = ws.onerror = null;
  71. }
  72. utils.unloadDel(this.unloadRef);
  73. this.unloadRef = this.ws = null;
  74. this.removeAllListeners();
  75. };
  76. WebSocketTransport.enabled = function() {
  77. debug('enabled');
  78. return !!WebsocketDriver;
  79. };
  80. WebSocketTransport.transportName = 'websocket';
  81. // In theory, ws should require 1 round trip. But in chrome, this is
  82. // not very stable over SSL. Most likely a ws connection requires a
  83. // separate SSL connection, in which case 2 round trips are an
  84. // absolute minumum.
  85. WebSocketTransport.roundTrips = 2;
  86. module.exports = WebSocketTransport;