uniapp,h5

websocket.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { Transport } from "../transport.js";
  2. import { pick, randomString } from "../util.js";
  3. import { encodePacket } from "engine.io-parser";
  4. import { globalThisShim as globalThis, nextTick } from "../globals.node.js";
  5. // detect ReactNative environment
  6. const isReactNative = typeof navigator !== "undefined" &&
  7. typeof navigator.product === "string" &&
  8. navigator.product.toLowerCase() === "reactnative";
  9. export class BaseWS extends Transport {
  10. get name() {
  11. return "websocket";
  12. }
  13. doOpen() {
  14. const uri = this.uri();
  15. const protocols = this.opts.protocols;
  16. // React Native only supports the 'headers' option, and will print a warning if anything else is passed
  17. const opts = isReactNative
  18. ? {}
  19. : pick(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
  20. if (this.opts.extraHeaders) {
  21. opts.headers = this.opts.extraHeaders;
  22. }
  23. try {
  24. this.ws = this.createSocket(uri, protocols, opts);
  25. }
  26. catch (err) {
  27. return this.emitReserved("error", err);
  28. }
  29. this.ws.binaryType = this.socket.binaryType;
  30. this.addEventListeners();
  31. }
  32. /**
  33. * Adds event listeners to the socket
  34. *
  35. * @private
  36. */
  37. addEventListeners() {
  38. this.ws.onopen = () => {
  39. if (this.opts.autoUnref) {
  40. this.ws._socket.unref();
  41. }
  42. this.onOpen();
  43. };
  44. this.ws.onclose = (closeEvent) => this.onClose({
  45. description: "websocket connection closed",
  46. context: closeEvent,
  47. });
  48. this.ws.onmessage = (ev) => this.onData(ev.data);
  49. this.ws.onerror = (e) => this.onError("websocket error", e);
  50. }
  51. write(packets) {
  52. this.writable = false;
  53. // encodePacket efficient as it uses WS framing
  54. // no need for encodePayload
  55. for (let i = 0; i < packets.length; i++) {
  56. const packet = packets[i];
  57. const lastPacket = i === packets.length - 1;
  58. encodePacket(packet, this.supportsBinary, (data) => {
  59. // Sometimes the websocket has already been closed but the browser didn't
  60. // have a chance of informing us about it yet, in that case send will
  61. // throw an error
  62. try {
  63. this.doWrite(packet, data);
  64. }
  65. catch (e) {
  66. }
  67. if (lastPacket) {
  68. // fake drain
  69. // defer to next tick to allow Socket to clear writeBuffer
  70. nextTick(() => {
  71. this.writable = true;
  72. this.emitReserved("drain");
  73. }, this.setTimeoutFn);
  74. }
  75. });
  76. }
  77. }
  78. doClose() {
  79. if (typeof this.ws !== "undefined") {
  80. this.ws.close();
  81. this.ws = null;
  82. }
  83. }
  84. /**
  85. * Generates uri for connection.
  86. *
  87. * @private
  88. */
  89. uri() {
  90. const schema = this.opts.secure ? "wss" : "ws";
  91. const query = this.query || {};
  92. // append timestamp to URI
  93. if (this.opts.timestampRequests) {
  94. query[this.opts.timestampParam] = randomString();
  95. }
  96. // communicate binary support capabilities
  97. if (!this.supportsBinary) {
  98. query.b64 = 1;
  99. }
  100. return this.createUri(schema, query);
  101. }
  102. }
  103. const WebSocketCtor = globalThis.WebSocket || globalThis.MozWebSocket;
  104. /**
  105. * WebSocket transport based on the built-in `WebSocket` object.
  106. *
  107. * Usage: browser, Node.js (since v21), Deno, Bun
  108. *
  109. * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
  110. * @see https://caniuse.com/mdn-api_websocket
  111. * @see https://nodejs.org/api/globals.html#websocket
  112. */
  113. export class WS extends BaseWS {
  114. createSocket(uri, protocols, opts) {
  115. return !isReactNative
  116. ? protocols
  117. ? new WebSocketCtor(uri, protocols)
  118. : new WebSocketCtor(uri)
  119. : new WebSocketCtor(uri, protocols, opts);
  120. }
  121. doWrite(_packet, data) {
  122. this.ws.send(data);
  123. }
  124. }