Source: lib/net/http_xhr_plugin.js

  1. /**
  2. * @license
  3. * Copyright 2016 Google Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. goog.provide('shaka.net.HttpXHRPlugin');
  18. goog.require('goog.asserts');
  19. goog.require('shaka.net.HttpPluginUtils');
  20. goog.require('shaka.net.NetworkingEngine');
  21. goog.require('shaka.util.AbortableOperation');
  22. goog.require('shaka.util.Error');
  23. /**
  24. * @namespace
  25. * @summary A networking plugin to handle http and https URIs via XHR.
  26. * @param {string} uri
  27. * @param {shakaExtern.Request} request
  28. * @param {shaka.net.NetworkingEngine.RequestType} requestType
  29. * @return {!shakaExtern.IAbortableOperation.<shakaExtern.Response>}
  30. * @export
  31. */
  32. shaka.net.HttpXHRPlugin = function(uri, request, requestType) {
  33. let xhr = new shaka.net.HttpXHRPlugin.xhr_();
  34. let promise = new Promise(function(resolve, reject) {
  35. xhr.open(request.method, uri, true);
  36. xhr.responseType = 'arraybuffer';
  37. xhr.timeout = request.retryParameters.timeout;
  38. xhr.withCredentials = request.allowCrossSiteCredentials;
  39. xhr.onabort = function() {
  40. reject(new shaka.util.Error(
  41. shaka.util.Error.Severity.RECOVERABLE,
  42. shaka.util.Error.Category.NETWORK,
  43. shaka.util.Error.Code.OPERATION_ABORTED,
  44. uri, requestType));
  45. };
  46. xhr.onload = function(event) {
  47. let target = event.target;
  48. goog.asserts.assert(target, 'XHR onload has no target!');
  49. // Since IE and Edge incorrectly return the header with a leading new line
  50. // character ('\n'), we trim the header here.
  51. let headers = target.getAllResponseHeaders().trim().split('\r\n').reduce(
  52. function(all, part) {
  53. /** @type {!Array.<string>} */
  54. let header = part.split(': ');
  55. all[header[0].toLowerCase()] = header.slice(1).join(': ');
  56. return all;
  57. },
  58. {});
  59. try {
  60. let response = shaka.net.HttpPluginUtils.makeResponse(headers,
  61. target.response, target.status, uri, target.responseURL,
  62. requestType);
  63. resolve(response);
  64. } catch (error) {
  65. goog.asserts.assert(error instanceof shaka.util.Error,
  66. 'Wrong error type!');
  67. reject(error);
  68. }
  69. };
  70. xhr.onerror = function(event) {
  71. reject(new shaka.util.Error(
  72. shaka.util.Error.Severity.RECOVERABLE,
  73. shaka.util.Error.Category.NETWORK,
  74. shaka.util.Error.Code.HTTP_ERROR,
  75. uri, event, requestType));
  76. };
  77. xhr.ontimeout = function(event) {
  78. reject(new shaka.util.Error(
  79. shaka.util.Error.Severity.RECOVERABLE,
  80. shaka.util.Error.Category.NETWORK,
  81. shaka.util.Error.Code.TIMEOUT,
  82. uri, requestType));
  83. };
  84. for (let key in request.headers) {
  85. // The Fetch API automatically normalizes outgoing header keys to
  86. // lowercase. For consistency's sake, do it here too.
  87. let lowercasedKey = key.toLowerCase();
  88. xhr.setRequestHeader(lowercasedKey, request.headers[key]);
  89. }
  90. xhr.send(request.body);
  91. });
  92. return new shaka.util.AbortableOperation(
  93. promise,
  94. () => {
  95. xhr.abort();
  96. return Promise.resolve();
  97. });
  98. };
  99. /**
  100. * Overridden in unit tests, but compiled out in production.
  101. *
  102. * @const {function(new: XMLHttpRequest)}
  103. * @private
  104. */
  105. shaka.net.HttpXHRPlugin.xhr_ = window.XMLHttpRequest;
  106. shaka.net.NetworkingEngine.registerScheme('http', shaka.net.HttpXHRPlugin,
  107. shaka.net.NetworkingEngine.PluginPriority.FALLBACK);
  108. shaka.net.NetworkingEngine.registerScheme('https', shaka.net.HttpXHRPlugin,
  109. shaka.net.NetworkingEngine.PluginPriority.FALLBACK);