xhrHttpClient.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See License.txt in the project root for license information.
  3. import { HttpHeaders } from "./httpHeaders";
  4. import { RestError } from "./restError";
  5. /**
  6. * A HttpClient implementation that uses XMLHttpRequest to send HTTP requests.
  7. */
  8. var XhrHttpClient = /** @class */ (function () {
  9. function XhrHttpClient() {
  10. }
  11. XhrHttpClient.prototype.sendRequest = function (request) {
  12. var xhr = new XMLHttpRequest();
  13. if (request.proxySettings) {
  14. throw new Error("HTTP proxy is not supported in browser environment");
  15. }
  16. var abortSignal = request.abortSignal;
  17. if (abortSignal) {
  18. var listener_1 = function () {
  19. xhr.abort();
  20. };
  21. abortSignal.addEventListener("abort", listener_1);
  22. xhr.addEventListener("readystatechange", function () {
  23. if (xhr.readyState === XMLHttpRequest.DONE) {
  24. abortSignal.removeEventListener("abort", listener_1);
  25. }
  26. });
  27. }
  28. addProgressListener(xhr.upload, request.onUploadProgress);
  29. addProgressListener(xhr, request.onDownloadProgress);
  30. if (request.formData) {
  31. var formData = request.formData;
  32. var requestForm_1 = new FormData();
  33. var appendFormValue = function (key, value) {
  34. if (value && value.hasOwnProperty("value") && value.hasOwnProperty("options")) {
  35. requestForm_1.append(key, value.value, value.options);
  36. }
  37. else {
  38. requestForm_1.append(key, value);
  39. }
  40. };
  41. for (var _i = 0, _a = Object.keys(formData); _i < _a.length; _i++) {
  42. var formKey = _a[_i];
  43. var formValue = formData[formKey];
  44. if (Array.isArray(formValue)) {
  45. for (var j = 0; j < formValue.length; j++) {
  46. appendFormValue(formKey, formValue[j]);
  47. }
  48. }
  49. else {
  50. appendFormValue(formKey, formValue);
  51. }
  52. }
  53. request.body = requestForm_1;
  54. request.formData = undefined;
  55. var contentType = request.headers.get("Content-Type");
  56. if (contentType && contentType.indexOf("multipart/form-data") !== -1) {
  57. // browser will automatically apply a suitable content-type header
  58. request.headers.remove("Content-Type");
  59. }
  60. }
  61. xhr.open(request.method, request.url);
  62. xhr.timeout = request.timeout;
  63. xhr.withCredentials = request.withCredentials;
  64. for (var _b = 0, _c = request.headers.headersArray(); _b < _c.length; _b++) {
  65. var header = _c[_b];
  66. xhr.setRequestHeader(header.name, header.value);
  67. }
  68. xhr.responseType = request.streamResponseBody ? "blob" : "text";
  69. // tslint:disable-next-line:no-null-keyword
  70. xhr.send(request.body === undefined ? null : request.body);
  71. if (request.streamResponseBody) {
  72. return new Promise(function (resolve, reject) {
  73. xhr.addEventListener("readystatechange", function () {
  74. // Resolve as soon as headers are loaded
  75. if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
  76. var blobBody = new Promise(function (resolve, reject) {
  77. xhr.addEventListener("load", function () {
  78. resolve(xhr.response);
  79. });
  80. rejectOnTerminalEvent(request, xhr, reject);
  81. });
  82. resolve({
  83. request: request,
  84. status: xhr.status,
  85. headers: parseHeaders(xhr),
  86. blobBody: blobBody
  87. });
  88. }
  89. });
  90. rejectOnTerminalEvent(request, xhr, reject);
  91. });
  92. }
  93. else {
  94. return new Promise(function (resolve, reject) {
  95. xhr.addEventListener("load", function () { return resolve({
  96. request: request,
  97. status: xhr.status,
  98. headers: parseHeaders(xhr),
  99. bodyAsText: xhr.responseText
  100. }); });
  101. rejectOnTerminalEvent(request, xhr, reject);
  102. });
  103. }
  104. };
  105. return XhrHttpClient;
  106. }());
  107. export { XhrHttpClient };
  108. function addProgressListener(xhr, listener) {
  109. if (listener) {
  110. xhr.addEventListener("progress", function (rawEvent) { return listener({
  111. loadedBytes: rawEvent.loaded
  112. }); });
  113. }
  114. }
  115. // exported locally for testing
  116. export function parseHeaders(xhr) {
  117. var responseHeaders = new HttpHeaders();
  118. var headerLines = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
  119. for (var _i = 0, headerLines_1 = headerLines; _i < headerLines_1.length; _i++) {
  120. var line = headerLines_1[_i];
  121. var index = line.indexOf(":");
  122. var headerName = line.slice(0, index);
  123. var headerValue = line.slice(index + 2);
  124. responseHeaders.set(headerName, headerValue);
  125. }
  126. return responseHeaders;
  127. }
  128. function rejectOnTerminalEvent(request, xhr, reject) {
  129. xhr.addEventListener("error", function () { return reject(new RestError("Failed to send request to " + request.url, RestError.REQUEST_SEND_ERROR, undefined, request)); });
  130. xhr.addEventListener("abort", function () { return reject(new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, request)); });
  131. xhr.addEventListener("timeout", function () { return reject(new RestError("timeout of " + xhr.timeout + "ms exceeded", RestError.REQUEST_SEND_ERROR, undefined, request)); });
  132. }
  133. //# sourceMappingURL=xhrHttpClient.js.map