JAVASCRIPT   5

eventsource.js

Guest on 21st May 2021 06:41:35 AM

  1. var API   = require('./websocket/api'),
  2.     Event = require('./websocket/api/event');
  3.  
  4. var isSecureConnection = function(request) {
  5.   if (request.headers['x-forwarded-proto']) {
  6.     return request.headers['x-forwarded-proto'] === 'https';
  7.   } else {
  8.     return (request.connection && request.connection.authorized !== undefined) ||
  9.            (request.socket && request.socket.secure);
  10.   }
  11. };
  12.  
  13. var EventSource = function(request, response, options) {
  14.   options = options || {};
  15.  
  16.   this._request  = request;
  17.   this._response = response;
  18.   this._stream   = response.socket;
  19.   this._ping     = options.ping  || this.DEFAULT_PING;
  20.   this._retry    = options.retry || this.DEFAULT_RETRY;
  21.  
  22.   var scheme = isSecureConnection(request) ? 'https:' : 'http:';
  23.   this.url = scheme + '//' + request.headers.host + request.url;
  24.  
  25.   this.lastEventId = request.headers['last-event-id'] || '';
  26.  
  27.   var self = this;
  28.   this.readyState = API.CONNECTING;
  29.   this._sendBuffer = [];
  30.   process.nextTick(function() { self._open() });
  31.  
  32.   var handshake = 'HTTP/1.1 200 OK\r\n' +
  33.                   'Content-Type: text/event-stream\r\n' +
  34.                   'Cache-Control: no-cache, no-store\r\n' +
  35.                   'Connection: close\r\n' +
  36.                   '\r\n\r\n' +
  37.                   'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n';
  38.  
  39.   this.readyState = API.OPEN;
  40.  
  41.   if (this._ping)
  42.     this._pingLoop = setInterval(function() { self.ping() }, this._ping * 1000);
  43.  
  44.   if (!this._stream || !this._stream.writable) return;
  45.  
  46.   this._stream.setTimeout(0);
  47.   this._stream.setNoDelay(true);
  48.  
  49.   try { this._stream.write(handshake, 'utf8') } catch (e) {}
  50.  
  51.   ['close', 'end', 'error'].forEach(function(event) {
  52.     self._stream.addListener(event, function() { self.close() });
  53.   });
  54. };
  55.  
  56. EventSource.isEventSource = function(request) {
  57.   var accept = (request.headers.accept || '').split(/\s*,\s*/);
  58.   return accept.indexOf('text/event-stream') >= 0;
  59. };
  60.  
  61. var instance = {
  62.   DEFAULT_PING:   10,
  63.   DEFAULT_RETRY:  5,
  64.  
  65.   send: function(message, options) {
  66.     if (this.readyState !== API.OPEN) return false;
  67.  
  68.     message = String(message).replace(/(\r\n|\r|\n)/g, '$1data: ');
  69.     options = options || {};
  70.  
  71.     var frame = '';
  72.     if (options.event) frame += 'event: ' + options.event + '\r\n';
  73.     if (options.id)    frame += 'id: '    + options.id    + '\r\n';
  74.     frame += 'data: ' + message + '\r\n\r\n';
  75.  
  76.     try {
  77.       this._stream.write(frame, 'utf8');
  78.       return true;
  79.     } catch (e) {
  80.       return false;
  81.     }
  82.   },
  83.  
  84.   ping: function() {
  85.     try {
  86.       this._stream.write(':\r\n\r\n', 'utf8');
  87.       return true;
  88.     } catch (e) {
  89.       return false;
  90.     }
  91.   },
  92.  
  93.   close: function() {
  94.     if (this.readyState === API.CLOSING || this.readyState === API.CLOSED)
  95.       return;
  96.  
  97.     this.readyState = API.CLOSED;
  98.     clearInterval(this._pingLoop);
  99.     this._response.end();
  100.  
  101.     var event = new Event('close');
  102.     event.initEvent('close', false, false);
  103.     this.dispatchEvent(event);
  104.   }
  105. };
  106.  
  107. for (var key in API) EventSource.prototype[key] = API[key];
  108. for (var key in instance) EventSource.prototype[key] = instance[key];
  109. module.exports = EventSource;

Raw Paste


Login or Register to edit or fork this paste. It's free.