fetch_stream.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. 'use strict';
  16. Object.defineProperty(exports, "__esModule", {
  17. value: true
  18. });
  19. exports.PDFFetchStream = undefined;
  20. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  21. var _util = require('../shared/util');
  22. var _network_utils = require('./network_utils');
  23. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  24. function createFetchOptions(headers, withCredentials) {
  25. return {
  26. method: 'GET',
  27. headers: headers,
  28. mode: 'cors',
  29. credentials: withCredentials ? 'omit' : 'include',
  30. redirect: 'follow'
  31. };
  32. }
  33. var PDFFetchStream = function () {
  34. function PDFFetchStream(options) {
  35. _classCallCheck(this, PDFFetchStream);
  36. this.options = options;
  37. this.source = options.source;
  38. this.isHttp = /^https?:/i.test(this.source.url);
  39. this.httpHeaders = this.isHttp && this.source.httpHeaders || {};
  40. this._fullRequestReader = null;
  41. this._rangeRequestReaders = [];
  42. }
  43. _createClass(PDFFetchStream, [{
  44. key: 'getFullReader',
  45. value: function getFullReader() {
  46. (0, _util.assert)(!this._fullRequestReader);
  47. this._fullRequestReader = new PDFFetchStreamReader(this);
  48. return this._fullRequestReader;
  49. }
  50. }, {
  51. key: 'getRangeReader',
  52. value: function getRangeReader(begin, end) {
  53. var reader = new PDFFetchStreamRangeReader(this, begin, end);
  54. this._rangeRequestReaders.push(reader);
  55. return reader;
  56. }
  57. }, {
  58. key: 'cancelAllRequests',
  59. value: function cancelAllRequests(reason) {
  60. if (this._fullRequestReader) {
  61. this._fullRequestReader.cancel(reason);
  62. }
  63. var readers = this._rangeRequestReaders.slice(0);
  64. readers.forEach(function (reader) {
  65. reader.cancel(reason);
  66. });
  67. }
  68. }]);
  69. return PDFFetchStream;
  70. }();
  71. var PDFFetchStreamReader = function () {
  72. function PDFFetchStreamReader(stream) {
  73. var _this = this;
  74. _classCallCheck(this, PDFFetchStreamReader);
  75. this._stream = stream;
  76. this._reader = null;
  77. this._loaded = 0;
  78. this._withCredentials = stream.source.withCredentials;
  79. this._contentLength = this._stream.source.length;
  80. this._headersCapability = (0, _util.createPromiseCapability)();
  81. this._disableRange = this._stream.options.disableRange;
  82. this._rangeChunkSize = this._stream.source.rangeChunkSize;
  83. if (!this._rangeChunkSize && !this._disableRange) {
  84. this._disableRange = true;
  85. }
  86. this._isRangeSupported = !this._stream.options.disableRange;
  87. this._isStreamingSupported = !this._stream.source.disableStream;
  88. this._headers = new Headers();
  89. for (var property in this._stream.httpHeaders) {
  90. var value = this._stream.httpHeaders[property];
  91. if (typeof value === 'undefined') {
  92. continue;
  93. }
  94. this._headers.append(property, value);
  95. }
  96. var url = this._stream.source.url;
  97. fetch(url, createFetchOptions(this._headers, this._withCredentials)).then(function (response) {
  98. if (!(0, _network_utils.validateResponseStatus)(response.status, _this._stream.isHttp)) {
  99. throw (0, _network_utils.createResponseStatusError)(response.status, url);
  100. }
  101. _this._reader = response.body.getReader();
  102. _this._headersCapability.resolve();
  103. var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
  104. getResponseHeader: function getResponseHeader(name) {
  105. return response.headers.get(name);
  106. },
  107. isHttp: _this._stream.isHttp,
  108. rangeChunkSize: _this._rangeChunkSize,
  109. disableRange: _this._disableRange
  110. }),
  111. allowRangeRequests = _validateRangeRequest.allowRangeRequests,
  112. suggestedLength = _validateRangeRequest.suggestedLength;
  113. _this._contentLength = suggestedLength;
  114. _this._isRangeSupported = allowRangeRequests;
  115. if (!_this._isStreamingSupported && _this._isRangeSupported) {
  116. _this.cancel(new _util.AbortException('streaming is disabled'));
  117. }
  118. }).catch(this._headersCapability.reject);
  119. this.onProgress = null;
  120. }
  121. _createClass(PDFFetchStreamReader, [{
  122. key: 'read',
  123. value: function read() {
  124. var _this2 = this;
  125. return this._headersCapability.promise.then(function () {
  126. return _this2._reader.read().then(function (_ref) {
  127. var value = _ref.value,
  128. done = _ref.done;
  129. if (done) {
  130. return Promise.resolve({
  131. value: value,
  132. done: done
  133. });
  134. }
  135. _this2._loaded += value.byteLength;
  136. if (_this2.onProgress) {
  137. _this2.onProgress({
  138. loaded: _this2._loaded,
  139. total: _this2._contentLength
  140. });
  141. }
  142. var buffer = new Uint8Array(value).buffer;
  143. return Promise.resolve({
  144. value: buffer,
  145. done: false
  146. });
  147. });
  148. });
  149. }
  150. }, {
  151. key: 'cancel',
  152. value: function cancel(reason) {
  153. if (this._reader) {
  154. this._reader.cancel(reason);
  155. }
  156. }
  157. }, {
  158. key: 'headersReady',
  159. get: function get() {
  160. return this._headersCapability.promise;
  161. }
  162. }, {
  163. key: 'contentLength',
  164. get: function get() {
  165. return this._contentLength;
  166. }
  167. }, {
  168. key: 'isRangeSupported',
  169. get: function get() {
  170. return this._isRangeSupported;
  171. }
  172. }, {
  173. key: 'isStreamingSupported',
  174. get: function get() {
  175. return this._isStreamingSupported;
  176. }
  177. }]);
  178. return PDFFetchStreamReader;
  179. }();
  180. var PDFFetchStreamRangeReader = function () {
  181. function PDFFetchStreamRangeReader(stream, begin, end) {
  182. var _this3 = this;
  183. _classCallCheck(this, PDFFetchStreamRangeReader);
  184. this._stream = stream;
  185. this._reader = null;
  186. this._loaded = 0;
  187. this._withCredentials = stream.source.withCredentials;
  188. this._readCapability = (0, _util.createPromiseCapability)();
  189. this._isStreamingSupported = !stream.source.disableStream;
  190. this._headers = new Headers();
  191. for (var property in this._stream.httpHeaders) {
  192. var value = this._stream.httpHeaders[property];
  193. if (typeof value === 'undefined') {
  194. continue;
  195. }
  196. this._headers.append(property, value);
  197. }
  198. var rangeStr = begin + '-' + (end - 1);
  199. this._headers.append('Range', 'bytes=' + rangeStr);
  200. var url = this._stream.source.url;
  201. fetch(url, createFetchOptions(this._headers, this._withCredentials)).then(function (response) {
  202. if (!(0, _network_utils.validateResponseStatus)(response.status, _this3._stream.isHttp)) {
  203. throw (0, _network_utils.createResponseStatusError)(response.status, url);
  204. }
  205. _this3._readCapability.resolve();
  206. _this3._reader = response.body.getReader();
  207. });
  208. this.onProgress = null;
  209. }
  210. _createClass(PDFFetchStreamRangeReader, [{
  211. key: 'read',
  212. value: function read() {
  213. var _this4 = this;
  214. return this._readCapability.promise.then(function () {
  215. return _this4._reader.read().then(function (_ref2) {
  216. var value = _ref2.value,
  217. done = _ref2.done;
  218. if (done) {
  219. return Promise.resolve({
  220. value: value,
  221. done: done
  222. });
  223. }
  224. _this4._loaded += value.byteLength;
  225. if (_this4.onProgress) {
  226. _this4.onProgress({ loaded: _this4._loaded });
  227. }
  228. var buffer = new Uint8Array(value).buffer;
  229. return Promise.resolve({
  230. value: buffer,
  231. done: false
  232. });
  233. });
  234. });
  235. }
  236. }, {
  237. key: 'cancel',
  238. value: function cancel(reason) {
  239. if (this._reader) {
  240. this._reader.cancel(reason);
  241. }
  242. }
  243. }, {
  244. key: 'isStreamingSupported',
  245. get: function get() {
  246. return this._isStreamingSupported;
  247. }
  248. }]);
  249. return PDFFetchStreamRangeReader;
  250. }();
  251. exports.PDFFetchStream = PDFFetchStream;