UNPKG

4.01 kBJavaScriptView Raw
1/*
2 Copyright 2018 Google LLC
3
4 Use of this source code is governed by an MIT-style
5 license that can be found in the LICENSE file or at
6 https://opensource.org/licenses/MIT.
7*/
8import { assert } from 'workbox-core/_private/assert.js';
9import '../_version.js';
10const serializableProperties = [
11 'method',
12 'referrer',
13 'referrerPolicy',
14 'mode',
15 'credentials',
16 'cache',
17 'redirect',
18 'integrity',
19 'keepalive',
20];
21/**
22 * A class to make it easier to serialize and de-serialize requests so they
23 * can be stored in IndexedDB.
24 *
25 * Most developers will not need to access this class directly;
26 * it is exposed for advanced use cases.
27 */
28class StorableRequest {
29 /**
30 * Converts a Request object to a plain object that can be structured
31 * cloned or JSON-stringified.
32 *
33 * @param {Request} request
34 * @return {Promise<StorableRequest>}
35 */
36 static async fromRequest(request) {
37 const requestData = {
38 url: request.url,
39 headers: {},
40 };
41 // Set the body if present.
42 if (request.method !== 'GET') {
43 // Use ArrayBuffer to support non-text request bodies.
44 // NOTE: we can't use Blobs becuse Safari doesn't support storing
45 // Blobs in IndexedDB in some cases:
46 // https://github.com/dfahlander/Dexie.js/issues/618#issuecomment-398348457
47 requestData.body = await request.clone().arrayBuffer();
48 }
49 // Convert the headers from an iterable to an object.
50 for (const [key, value] of request.headers.entries()) {
51 requestData.headers[key] = value;
52 }
53 // Add all other serializable request properties
54 for (const prop of serializableProperties) {
55 if (request[prop] !== undefined) {
56 requestData[prop] = request[prop];
57 }
58 }
59 return new StorableRequest(requestData);
60 }
61 /**
62 * Accepts an object of request data that can be used to construct a
63 * `Request` but can also be stored in IndexedDB.
64 *
65 * @param {Object} requestData An object of request data that includes the
66 * `url` plus any relevant properties of
67 * [requestInit]{@link https://fetch.spec.whatwg.org/#requestinit}.
68 */
69 constructor(requestData) {
70 if (process.env.NODE_ENV !== 'production') {
71 assert.isType(requestData, 'object', {
72 moduleName: 'workbox-background-sync',
73 className: 'StorableRequest',
74 funcName: 'constructor',
75 paramName: 'requestData',
76 });
77 assert.isType(requestData.url, 'string', {
78 moduleName: 'workbox-background-sync',
79 className: 'StorableRequest',
80 funcName: 'constructor',
81 paramName: 'requestData.url',
82 });
83 }
84 // If the request's mode is `navigate`, convert it to `same-origin` since
85 // navigation requests can't be constructed via script.
86 if (requestData['mode'] === 'navigate') {
87 requestData['mode'] = 'same-origin';
88 }
89 this._requestData = requestData;
90 }
91 /**
92 * Returns a deep clone of the instances `_requestData` object.
93 *
94 * @return {Object}
95 */
96 toObject() {
97 const requestData = Object.assign({}, this._requestData);
98 requestData.headers = Object.assign({}, this._requestData.headers);
99 if (requestData.body) {
100 requestData.body = requestData.body.slice(0);
101 }
102 return requestData;
103 }
104 /**
105 * Converts this instance to a Request.
106 *
107 * @return {Request}
108 */
109 toRequest() {
110 return new Request(this._requestData.url, this._requestData);
111 }
112 /**
113 * Creates and returns a deep clone of the instance.
114 *
115 * @return {StorableRequest}
116 */
117 clone() {
118 return new StorableRequest(this.toObject());
119 }
120}
121export { StorableRequest };