UNPKG

10.8 kBJavaScriptView Raw
1this.workbox = this.workbox || {};
2this.workbox.rangeRequests = (function (exports,WorkboxError_mjs,assert_mjs,logger_mjs) {
3 'use strict';
4
5 try {
6 self.workbox.v['workbox:range-requests:3.6.2'] = 1;
7 } catch (e) {} // eslint-disable-line
8
9 /*
10 Copyright 2017 Google Inc.
11
12 Licensed under the Apache License, Version 2.0 (the "License");
13 you may not use this file except in compliance with the License.
14 You may obtain a copy of the License at
15
16 https://www.apache.org/licenses/LICENSE-2.0
17
18 Unless required by applicable law or agreed to in writing, software
19 distributed under the License is distributed on an "AS IS" BASIS,
20 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 See the License for the specific language governing permissions and
22 limitations under the License.
23 */
24
25 /**
26 * @param {Blob} blob A source blob.
27 * @param {number|null} start The offset to use as the start of the
28 * slice.
29 * @param {number|null} end The offset to use as the end of the slice.
30 * @return {Object} An object with `start` and `end` properties, reflecting
31 * the effective boundaries to use given the size of the blob.
32 *
33 * @private
34 */
35 function calculateEffectiveBoundaries(blob, start, end) {
36 {
37 assert_mjs.assert.isInstance(blob, Blob, {
38 moduleName: 'workbox-range-requests',
39 funcName: 'calculateEffectiveBoundaries',
40 paramName: 'blob'
41 });
42 }
43
44 const blobSize = blob.size;
45
46 if (end > blobSize || start < 0) {
47 throw new WorkboxError_mjs.WorkboxError('range-not-satisfiable', {
48 size: blobSize,
49 end,
50 start
51 });
52 }
53
54 let effectiveStart;
55 let effectiveEnd;
56
57 if (start === null) {
58 effectiveStart = blobSize - end;
59 effectiveEnd = blobSize;
60 } else if (end === null) {
61 effectiveStart = start;
62 effectiveEnd = blobSize;
63 } else {
64 effectiveStart = start;
65 // Range values are inclusive, so add 1 to the value.
66 effectiveEnd = end + 1;
67 }
68
69 return {
70 start: effectiveStart,
71 end: effectiveEnd
72 };
73 }
74
75 /*
76 Copyright 2017 Google Inc.
77
78 Licensed under the Apache License, Version 2.0 (the "License");
79 you may not use this file except in compliance with the License.
80 You may obtain a copy of the License at
81
82 https://www.apache.org/licenses/LICENSE-2.0
83
84 Unless required by applicable law or agreed to in writing, software
85 distributed under the License is distributed on an "AS IS" BASIS,
86 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
87 See the License for the specific language governing permissions and
88 limitations under the License.
89 */
90
91 /**
92 * @param {string} rangeHeader A Range: header value.
93 * @return {Object} An object with `start` and `end` properties, reflecting
94 * the parsed value of the Range: header. If either the `start` or `end` are
95 * omitted, then `null` will be returned.
96 *
97 * @private
98 */
99 function parseRangeHeader(rangeHeader) {
100 {
101 assert_mjs.assert.isType(rangeHeader, 'string', {
102 moduleName: 'workbox-range-requests',
103 funcName: 'parseRangeHeader',
104 paramName: 'rangeHeader'
105 });
106 }
107
108 const normalizedRangeHeader = rangeHeader.trim().toLowerCase();
109 if (!normalizedRangeHeader.startsWith('bytes=')) {
110 throw new WorkboxError_mjs.WorkboxError('unit-must-be-bytes', { normalizedRangeHeader });
111 }
112
113 // Specifying multiple ranges separate by commas is valid syntax, but this
114 // library only attempts to handle a single, contiguous sequence of bytes.
115 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#Syntax
116 if (normalizedRangeHeader.includes(',')) {
117 throw new WorkboxError_mjs.WorkboxError('single-range-only', { normalizedRangeHeader });
118 }
119
120 const rangeParts = /(\d*)-(\d*)/.exec(normalizedRangeHeader);
121 // We need either at least one of the start or end values.
122 if (rangeParts === null || !(rangeParts[1] || rangeParts[2])) {
123 throw new WorkboxError_mjs.WorkboxError('invalid-range-values', { normalizedRangeHeader });
124 }
125
126 return {
127 start: rangeParts[1] === '' ? null : Number(rangeParts[1]),
128 end: rangeParts[2] === '' ? null : Number(rangeParts[2])
129 };
130 }
131
132 /**
133 * Given a `Request` and `Response` objects as input, this will return a
134 * promise for a new `Response`.
135 *
136 * @param {Request} request A request, which should contain a Range:
137 * header.
138 * @param {Response} originalResponse An original response containing the full
139 * content.
140 * @return {Promise<Response>} Either a `206 Partial Content` response, with
141 * the response body set to the slice of content specified by the request's
142 * `Range:` header, or a `416 Range Not Satisfiable` response if the
143 * conditions of the `Range:` header can't be met.
144 *
145 * @memberof workbox.rangeRequests
146 */
147 let createPartialResponse = (() => {
148 var _ref = babelHelpers.asyncToGenerator(function* (request, originalResponse) {
149 try {
150 {
151 assert_mjs.assert.isInstance(request, Request, {
152 moduleName: 'workbox-range-requests',
153 funcName: 'createPartialResponse',
154 paramName: 'request'
155 });
156
157 assert_mjs.assert.isInstance(originalResponse, Response, {
158 moduleName: 'workbox-range-requests',
159 funcName: 'createPartialResponse',
160 paramName: 'originalResponse'
161 });
162 }
163
164 const rangeHeader = request.headers.get('range');
165 if (!rangeHeader) {
166 throw new WorkboxError_mjs.WorkboxError('no-range-header');
167 }
168
169 const boundaries = parseRangeHeader(rangeHeader);
170 const originalBlob = yield originalResponse.blob();
171
172 const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);
173
174 const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);
175 const slicedBlobSize = slicedBlob.size;
176
177 const slicedResponse = new Response(slicedBlob, {
178 // Status code 206 is for a Partial Content response.
179 // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206
180 status: 206,
181 statusText: 'Partial Content',
182 headers: originalResponse.headers
183 });
184
185 slicedResponse.headers.set('Content-Length', slicedBlobSize);
186 slicedResponse.headers.set('Content-Range', `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + originalBlob.size);
187
188 return slicedResponse;
189 } catch (error) {
190 {
191 logger_mjs.logger.warn(`Unable to construct a partial response; returning a ` + `416 Range Not Satisfiable response instead.`);
192 logger_mjs.logger.groupCollapsed(`View details here.`);
193 logger_mjs.logger.unprefixed.log(error);
194 logger_mjs.logger.unprefixed.log(request);
195 logger_mjs.logger.unprefixed.log(originalResponse);
196 logger_mjs.logger.groupEnd();
197 }
198
199 return new Response('', {
200 status: 416,
201 statusText: 'Range Not Satisfiable'
202 });
203 }
204 });
205
206 return function createPartialResponse(_x, _x2) {
207 return _ref.apply(this, arguments);
208 };
209 })();
210
211 /*
212 Copyright 2016 Google Inc. All Rights Reserved.
213 Licensed under the Apache License, Version 2.0 (the "License");
214 you may not use this file except in compliance with the License.
215 You may obtain a copy of the License at
216 http://www.apache.org/licenses/LICENSE-2.0
217 Unless required by applicable law or agreed to in writing, software
218 distributed under the License is distributed on an "AS IS" BASIS,
219 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
220 See the License for the specific language governing permissions and
221 limitations under the License.
222 */
223
224 /**
225 * The range request plugin makes it easy for a request with a 'Range' header to
226 * be fulfilled by a cached response.
227 *
228 * It does this by intercepting the `cachedResponseWillBeUsed` plugin callback
229 * and returning the appropriate subset of the cached response body.
230 *
231 * @memberof workbox.rangeRequests
232 */
233 class Plugin {
234 /**
235 * @param {Object} options
236 * @param {Request} options.request The original request, which may or may not
237 * contain a Range: header.
238 * @param {Response} options.cachedResponse The complete cached response.
239 * @return {Promise<Response>} If request contains a 'Range' header, then a
240 * new response with status 206 whose body is a subset of `cachedResponse` is
241 * returned. Otherwise, `cachedResponse` is returned as-is.
242 *
243 * @private
244 */
245 cachedResponseWillBeUsed({ request, cachedResponse }) {
246 return babelHelpers.asyncToGenerator(function* () {
247 // Only return a sliced response if there's something valid in the cache,
248 // and there's a Range: header in the request.
249 if (cachedResponse && request.headers.has('range')) {
250 return yield createPartialResponse(request, cachedResponse);
251 }
252
253 // If there was no Range: header, or if cachedResponse wasn't valid, just
254 // pass it through as-is.
255 return cachedResponse;
256 })();
257 }
258 }
259
260 /*
261 Copyright 2017 Google Inc.
262
263 Licensed under the Apache License, Version 2.0 (the "License");
264 you may not use this file except in compliance with the License.
265 You may obtain a copy of the License at
266
267 https://www.apache.org/licenses/LICENSE-2.0
268
269 Unless required by applicable law or agreed to in writing, software
270 distributed under the License is distributed on an "AS IS" BASIS,
271 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
272 See the License for the specific language governing permissions and
273 limitations under the License.
274 */
275
276 /*
277 Copyright 2017 Google Inc.
278
279 Licensed under the Apache License, Version 2.0 (the "License");
280 you may not use this file except in compliance with the License.
281 You may obtain a copy of the License at
282
283 https://www.apache.org/licenses/LICENSE-2.0
284
285 Unless required by applicable law or agreed to in writing, software
286 distributed under the License is distributed on an "AS IS" BASIS,
287 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
288 See the License for the specific language governing permissions and
289 limitations under the License.
290 */
291
292 exports.createPartialResponse = createPartialResponse;
293 exports.Plugin = Plugin;
294
295 return exports;
296
297}({},workbox.core._private,workbox.core._private,workbox.core._private));
298
299//# sourceMappingURL=workbox-range-requests.dev.js.map