You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.4 KiB

4 years ago
  1. 'use strict';
  2. var EventEmitter = require('events').EventEmitter
  3. , inherits = require('inherits')
  4. , eventUtils = require('../../utils/event')
  5. , browser = require('../../utils/browser')
  6. , urlUtils = require('../../utils/url')
  7. ;
  8. var debug = function() {};
  9. if (process.env.NODE_ENV !== 'production') {
  10. debug = require('debug')('sockjs-client:sender:xdr');
  11. }
  12. // References:
  13. // http://ajaxian.com/archives/100-line-ajax-wrapper
  14. // http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
  15. function XDRObject(method, url, payload) {
  16. debug(method, url);
  17. var self = this;
  18. EventEmitter.call(this);
  19. setTimeout(function() {
  20. self._start(method, url, payload);
  21. }, 0);
  22. }
  23. inherits(XDRObject, EventEmitter);
  24. XDRObject.prototype._start = function(method, url, payload) {
  25. debug('_start');
  26. var self = this;
  27. var xdr = new global.XDomainRequest();
  28. // IE caches even POSTs
  29. url = urlUtils.addQuery(url, 't=' + (+new Date()));
  30. xdr.onerror = function() {
  31. debug('onerror');
  32. self._error();
  33. };
  34. xdr.ontimeout = function() {
  35. debug('ontimeout');
  36. self._error();
  37. };
  38. xdr.onprogress = function() {
  39. debug('progress', xdr.responseText);
  40. self.emit('chunk', 200, xdr.responseText);
  41. };
  42. xdr.onload = function() {
  43. debug('load');
  44. self.emit('finish', 200, xdr.responseText);
  45. self._cleanup(false);
  46. };
  47. this.xdr = xdr;
  48. this.unloadRef = eventUtils.unloadAdd(function() {
  49. self._cleanup(true);
  50. });
  51. try {
  52. // Fails with AccessDenied if port number is bogus
  53. this.xdr.open(method, url);
  54. if (this.timeout) {
  55. this.xdr.timeout = this.timeout;
  56. }
  57. this.xdr.send(payload);
  58. } catch (x) {
  59. this._error();
  60. }
  61. };
  62. XDRObject.prototype._error = function() {
  63. this.emit('finish', 0, '');
  64. this._cleanup(false);
  65. };
  66. XDRObject.prototype._cleanup = function(abort) {
  67. debug('cleanup', abort);
  68. if (!this.xdr) {
  69. return;
  70. }
  71. this.removeAllListeners();
  72. eventUtils.unloadDel(this.unloadRef);
  73. this.xdr.ontimeout = this.xdr.onerror = this.xdr.onprogress = this.xdr.onload = null;
  74. if (abort) {
  75. try {
  76. this.xdr.abort();
  77. } catch (x) {
  78. // intentionally empty
  79. }
  80. }
  81. this.unloadRef = this.xdr = null;
  82. };
  83. XDRObject.prototype.close = function() {
  84. debug('close');
  85. this._cleanup(true);
  86. };
  87. // IE 8/9 if the request target uses the same scheme - #79
  88. XDRObject.enabled = !!(global.XDomainRequest && browser.hasDomain());
  89. module.exports = XDRObject;