BestHTTP_WebRequest.jslib 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // https://docs.unity3d.com/6000.0/Documentation/Manual/web-interacting-browser-deprecated.html
  2. // Deprecated code | Replacement code
  3. // -----------------+-----------------
  4. // dynCall() | makeDynCall()
  5. var Lib_BEST_HTTP_WebGL_HTTP_Bridge =
  6. {
  7. /*LogLevels: {
  8. All: 0,
  9. Information: 1,
  10. Warning: 2,
  11. Error: 3,
  12. Exception: 4,
  13. None: 5
  14. }*/
  15. $_best_http_request_bridge_global: {
  16. requestInstances: {},
  17. nextRequestId: 1,
  18. loglevel: 2,
  19. SendTextToCSharpSide: function(request, onbuffer, text)
  20. {
  21. const encoder = new TextEncoder();
  22. const byteArray = encoder.encode(text);
  23. const array = {{{ makeDynCall('iii', '_best_http_request_bridge_global.onallocbuffer') }}}(request, byteArray.length);
  24. HEAPU8.set(byteArray, array);
  25. {{{ makeDynCall('viii', 'onbuffer') }}}(request, array, byteArray.length);
  26. },
  27. GetResponseHeaders: function(request, callback)
  28. {
  29. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  30. console.log(`GetResponseHeaders(${request})`);
  31. var headers = '';
  32. var cookies = document.cookie.split(';');
  33. for(var i = 0; i < cookies.length; ++i) {
  34. const cookie = cookies[i].trim();
  35. if (cookie.length > 0)
  36. headers += "Set-Cookie:" + cookie + "\n";
  37. }
  38. const arr = _best_http_request_bridge_global.requestInstances[request].getAllResponseHeaders().trim().split(/[\r\n]+/);
  39. arr.forEach((line) => {
  40. const parts = line.split(": ");
  41. const header = parts.shift();
  42. const value = parts.join(": ");
  43. // Skip 'content-length' header. If there's any content-encoding (gzip for example),
  44. // the actual content accessible through XHR's response will have different length (it's uncompressed).
  45. // So we have to remove the header here, and reconstruct it later when the actual content size is known.
  46. if (header !== 'content-length')
  47. headers += `${header}:${value}\n`;
  48. });
  49. _best_http_request_bridge_global.SendTextToCSharpSide(request, callback, headers);
  50. },
  51. },
  52. XHR_Create: function(method, url, user, passwd, withCredentials)
  53. {
  54. var _url = new URL(UTF8ToString(url));
  55. var _method = UTF8ToString(method);
  56. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  57. console.log(`XHR_Create (${_best_http_request_bridge_global.nextRequestId}, ${_method}, ${_url.toString()}, ${withCredentials})`);
  58. var http = new XMLHttpRequest();
  59. if (user && passwd)
  60. {
  61. var u = UTF8ToString(user);
  62. var p = UTF8ToString(passwd);
  63. // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
  64. http.withCredentials = true;
  65. http.open(_method, _url.toString(), /*async:*/ true , u, p);
  66. }
  67. else {
  68. http.withCredentials = withCredentials;
  69. http.open(_method, _url.toString(), /*async:*/ true);
  70. }
  71. http.responseType = 'arraybuffer';
  72. _best_http_request_bridge_global.requestInstances[_best_http_request_bridge_global.nextRequestId] = http;
  73. return _best_http_request_bridge_global.nextRequestId++;
  74. },
  75. XHR_SetTimeout: function (request, timeout)
  76. {
  77. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  78. console.log(`XHR_SetTimeout(${request}, ${timeout})`);
  79. _best_http_request_bridge_global.requestInstances[request].timeout = timeout;
  80. },
  81. XHR_SetRequestHeader: function (request, header, value)
  82. {
  83. var _header = UTF8ToString(header);
  84. var _value = UTF8ToString(value);
  85. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  86. console.log(`XHR_SetRequestHeader(${_header}, ${_value})`);
  87. if (_header != 'Cookie')
  88. _best_http_request_bridge_global.requestInstances[request].setRequestHeader(_header, _value);
  89. else {
  90. var cookies = _value.split(';');
  91. for (var i = 0; i < cookies.length; i++) {
  92. document.cookie = cookies[i];
  93. }
  94. }
  95. },
  96. XHR_SetResponseHandler: function (request, onresponse, onerror, ontimeout, onaborted, onbuffer, onallocbuffer)
  97. {
  98. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  99. console.log(`XHR_SetResponseHandler(${request})`);
  100. _best_http_request_bridge_global.onallocbuffer = onallocbuffer;
  101. var http = _best_http_request_bridge_global.requestInstances[request];
  102. // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readystatechange_event
  103. // The readystatechange event is fired whenever the readyState property of the XMLHttpRequest changes.
  104. // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
  105. http.onreadystatechange = (event) => {
  106. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  107. console.log(`${request} onreadystatechange(${http.readyState})`);
  108. switch (http.readyState){
  109. // The object has been constructed.
  110. case XMLHttpRequest.UNSENT: break;
  111. // The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the fetch can be initiated using the send() method.
  112. case XMLHttpRequest.OPENED: break;
  113. // All redirects (if any) have been followed and all headers of a response have been received.
  114. case XMLHttpRequest.HEADERS_RECEIVED: {
  115. _best_http_request_bridge_global.SendTextToCSharpSide(request, onbuffer, `HTTP/1.1 ${http.status} ${http.statusText}\n`);
  116. _best_http_request_bridge_global.GetResponseHeaders(request, onbuffer);
  117. break;
  118. }
  119. // The response body is being received.
  120. case XMLHttpRequest.LOADING: break;
  121. // The data transfer has been completed or something went wrong during the transfer (e.g., infinite redirects).
  122. case XMLHttpRequest.DONE: break;
  123. }
  124. };
  125. http.onloadstart = (event) => {
  126. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  127. console.log(`${request} onloadstart: ${event}`);
  128. };
  129. // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/load_event
  130. // Fired when an XMLHttpRequest transaction completes successfully. Also available via the onload event handler property.
  131. http.onload = function http_onload(e) {
  132. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  133. console.log(`${request} onload(${http.status}, ${http.statusText})`);
  134. if (onresponse)
  135. {
  136. var responseLength = 0;
  137. var array = 0;
  138. if (!!http.response) {
  139. var response = http.response;
  140. responseLength = response.byteLength;
  141. _best_http_request_bridge_global.SendTextToCSharpSide(request, onbuffer, `content-length:${responseLength}\n\n`);
  142. array = {{{ makeDynCall('iii', 'onallocbuffer') }}}(request, responseLength);
  143. var responseBytes = new Uint8Array(response);
  144. var buffer = HEAPU8.subarray(array, array + responseLength);
  145. buffer.set(responseBytes)
  146. }
  147. else {
  148. _best_http_request_bridge_global.SendTextToCSharpSide(request, onbuffer, `content-length:0\n\n`);
  149. }
  150. {{{ makeDynCall('viii', 'onresponse') }}}(request, array, responseLength);
  151. }
  152. };
  153. if (onerror)
  154. {
  155. http.onerror = function http_onerror(e) {
  156. function HandleError(err)
  157. {
  158. var length = lengthBytesUTF8(err) + 1;
  159. var buffer = _malloc(length);
  160. stringToUTF8Array(err, HEAPU8, buffer, length);
  161. {{{ makeDynCall('vii', 'onerror') }}}(request, buffer);
  162. _free(buffer);
  163. }
  164. if (e.error)
  165. HandleError(e.error);
  166. else
  167. HandleError("Unknown Error! Maybe a CORS porblem?");
  168. };
  169. }
  170. if (ontimeout)
  171. http.ontimeout = function http_onerror(e) {
  172. {{{ makeDynCall('vi', 'ontimeout') }}}(request);
  173. };
  174. if (onaborted)
  175. http.onabort = function http_onerror(e) {
  176. {{{ makeDynCall('vi', 'onaborted') }}}(request);
  177. };
  178. },
  179. XHR_SetProgressHandler: function (request, onprogress, onuploadprogress)
  180. {
  181. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  182. console.log(`XHR_SetProgressHandler(${request})`);
  183. var http = _best_http_request_bridge_global.requestInstances[request];
  184. if (http)
  185. {
  186. if (onprogress)
  187. http.onprogress = function http_onprogress(e) {
  188. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  189. console.log(`XHR_SetProgressHandler download(${request}, ${e.loaded}, ${e.total})`);
  190. if (e.lengthComputable) {
  191. {{{ makeDynCall('viii', 'onprogress') }}}(request, e.loaded, e.total);
  192. }
  193. };
  194. if (onuploadprogress)
  195. http.upload.addEventListener("progress", function http_onprogress(e) {
  196. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  197. console.log(`XHR_SetProgressHandler upload(${request}, ${e.loaded}, ${e.total})`);
  198. if (e.lengthComputable) {
  199. {{{ makeDynCall('viii', 'onuploadprogress') }}}(request, e.loaded, e.total);
  200. }
  201. }, true);
  202. }
  203. },
  204. XHR_Send: function (request, ptr, length)
  205. {
  206. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  207. console.log(`XHR_Send(${request}, ${ptr}, ${length})`);
  208. var http = _best_http_request_bridge_global.requestInstances[request];
  209. try {
  210. if (length > 0)
  211. http.send(HEAPU8.subarray(ptr, ptr+length));
  212. else
  213. http.send();
  214. }
  215. catch(e) {
  216. if (_best_http_request_bridge_global.loglevel <= 4) /*exception*/
  217. console.error(`XHR_Send(${request}): ${e.name} : ${e.message}`);
  218. }
  219. },
  220. XHR_Abort: function (request)
  221. {
  222. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  223. console.log(`XHR_Abort(${request})`);
  224. _best_http_request_bridge_global.requestInstances[request].abort();
  225. },
  226. XHR_Release: function (request)
  227. {
  228. if (_best_http_request_bridge_global.loglevel <= 1) /*information*/
  229. console.log(`XHR_Release(${request})`);
  230. delete _best_http_request_bridge_global.requestInstances[request];
  231. },
  232. XHR_SetLoglevel: function (level)
  233. {
  234. _best_http_request_bridge_global.loglevel = level;
  235. }
  236. };
  237. autoAddDeps(Lib_BEST_HTTP_WebGL_HTTP_Bridge, '$_best_http_request_bridge_global');
  238. mergeInto(LibraryManager.library, Lib_BEST_HTTP_WebGL_HTTP_Bridge);