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.

99 lines
2.4 KiB

4 years ago
  1. 'use strict';
  2. var random = require('../../utils/random')
  3. , urlUtils = require('../../utils/url')
  4. ;
  5. var debug = function() {};
  6. if (process.env.NODE_ENV !== 'production') {
  7. debug = require('debug')('sockjs-client:sender:jsonp');
  8. }
  9. var form, area;
  10. function createIframe(id) {
  11. debug('createIframe', id);
  12. try {
  13. // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
  14. return global.document.createElement('<iframe name="' + id + '">');
  15. } catch (x) {
  16. var iframe = global.document.createElement('iframe');
  17. iframe.name = id;
  18. return iframe;
  19. }
  20. }
  21. function createForm() {
  22. debug('createForm');
  23. form = global.document.createElement('form');
  24. form.style.display = 'none';
  25. form.style.position = 'absolute';
  26. form.method = 'POST';
  27. form.enctype = 'application/x-www-form-urlencoded';
  28. form.acceptCharset = 'UTF-8';
  29. area = global.document.createElement('textarea');
  30. area.name = 'd';
  31. form.appendChild(area);
  32. global.document.body.appendChild(form);
  33. }
  34. module.exports = function(url, payload, callback) {
  35. debug(url, payload);
  36. if (!form) {
  37. createForm();
  38. }
  39. var id = 'a' + random.string(8);
  40. form.target = id;
  41. form.action = urlUtils.addQuery(urlUtils.addPath(url, '/jsonp_send'), 'i=' + id);
  42. var iframe = createIframe(id);
  43. iframe.id = id;
  44. iframe.style.display = 'none';
  45. form.appendChild(iframe);
  46. try {
  47. area.value = payload;
  48. } catch (e) {
  49. // seriously broken browsers get here
  50. }
  51. form.submit();
  52. var completed = function(err) {
  53. debug('completed', id, err);
  54. if (!iframe.onerror) {
  55. return;
  56. }
  57. iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
  58. // Opera mini doesn't like if we GC iframe
  59. // immediately, thus this timeout.
  60. setTimeout(function() {
  61. debug('cleaning up', id);
  62. iframe.parentNode.removeChild(iframe);
  63. iframe = null;
  64. }, 500);
  65. area.value = '';
  66. // It is not possible to detect if the iframe succeeded or
  67. // failed to submit our form.
  68. callback(err);
  69. };
  70. iframe.onerror = function() {
  71. debug('onerror', id);
  72. completed();
  73. };
  74. iframe.onload = function() {
  75. debug('onload', id);
  76. completed();
  77. };
  78. iframe.onreadystatechange = function(e) {
  79. debug('onreadystatechange', id, iframe.readyState, e);
  80. if (iframe.readyState === 'complete') {
  81. completed();
  82. }
  83. };
  84. return function() {
  85. debug('aborted', id);
  86. completed(new Error('Aborted'));
  87. };
  88. };