From 94b4875e6e5d66366cb1af05cb4d31b7536e79da Mon Sep 17 00:00:00 2001 From: Jaifroid Date: Sun, 16 Jan 2022 15:57:48 +0000 Subject: [PATCH] Ensure cache sets headers correctly Former-commit-id: 7276a93b4b0477df5cae9f7b10a7e10052450720 [formerly dcb061d302b0f1ff155d7fd4a131a03bc14b5a42] [formerly aef4a88244a9e6ea512e07e3faa58e3c89fc5833] [formerly e58989a211266298a5e214644ed03e6e0fd8e2f7 [formerly 37e943929a2f18bc6b358a446420f5171ba3dc8a [formerly 6e831cf3a4c9ba1dbe773f76527d72aca35f1030]]] Former-commit-id: 27b52ecff50141910e8dfdccfbc5c18e06f86fd5 [formerly 806562e714f4e4f57f4fe9c8a3681fe88d06d63a [formerly b74a91dfca17333645c4201e5e3064a3ade83a94]] Former-commit-id: 8d76a10257d226d0ccc19a6be7c0e2fd4c7da677 [formerly bdf9e98f25809ba1ea5e15b3f672951c307697a1] Former-commit-id: b754de747077bfc1dcdac476f0283f78ce893ff2 --- www/js/lib/cache.js | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/www/js/lib/cache.js b/www/js/lib/cache.js index 117eaa21..608dbf04 100644 --- a/www/js/lib/cache.js +++ b/www/js/lib/cache.js @@ -250,8 +250,9 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { * 'delete' (deletes a record with key passed in valueOrCallback) * @param {Variable} valueOrCallback The value to write, or a callback function for read and command transactions * @param {Function} callback Callback for write transactions only + * @param {String} mimetype The MIME type of any content to be stored */ - function cacheAPI(keyOrCommand, valueOrCallback, callback) { + function cacheAPI(keyOrCommand, valueOrCallback, callback, mimetype) { var value = callback ? valueOrCallback : null; var rtnFn = callback || valueOrCallback; // Process commands @@ -280,9 +281,25 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { } else { // Request storing of data in cache caches.open(CACHEAPI).then(function(cache) { - // Construct a Response from value - var response = new Response(value); - cache.put('../' + keyOrCommand, response).then(function() { + var contentLength; + if (typeof value === 'string') { + var m = encodeURIComponent(value).match(/%[89ABab]/g); + contentLength = value.length + (m ? m.length : 0); + } else { + contentLength = value.byteLength || value.length; + } + var headers = new Headers(); + if (contentLength) headers.set('Content-Length', contentLength); + // Prevent CORS issues in PWAs + if (contentLength) headers.set('Access-Control-Allow-Origin', '*'); + if (mimetype) headers.set('Content-Type', mimetype); + var responseInit = { + status: 200, + statusText: 'OK', + headers: headers + }; + var httpResponse = new Response(value, responseInit); + cache.put('../' + keyOrCommand, httpResponse).then(function() { rtnFn(true); }).catch(function(err) { console.error('Unable to store assets in Cache API!', err); @@ -307,7 +324,7 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { return; } settingsStore.setItem(zimFile, article, Infinity); - setItem(zimFile, content, function(response) { + setItem(zimFile, content, 'text/html', function(response) { callback(response); }); } @@ -333,9 +350,10 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { * * @param {String} key The database key of the asset to cache * @param {String} contents The file contents to be stored in the cache + * @param {String} mimetype The MIME type of the contents * @param {Function} callback Callback function to report outcome of operation */ - function setItem(key, contents, callback) { + function setItem(key, contents, mimetype, callback) { // Prevent use of storage if user has deselected the option in Configuration // or if the asset is of the wrong type if (params.assetsCache === false || !regexpKeyTypes.test(key)) { @@ -363,7 +381,7 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { } else if (/^cacheAPI/.test(assetsCache.capability)) { cacheAPI(key, contents, function(result) { callback(result); - }); + }, mimetype); } else { callback(key); } @@ -420,7 +438,8 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { * @param {Object} selectedArchive The ZIM archive picked by the user * @param {String} key The cache key of the item to retrieve * @param {Object} dirEntry If the item's dirEntry has already been looked up, it can optionally be - * supplied here (saves a redundant dirEntry lookup) + * supplied here (saves a redundant dirEntry lookup) + * @returns {Promise} A Promise for the content */ function getItemFromCacheOrZIM(selectedArchive, key, dirEntry) { return new Promise(function (resolve, reject) { @@ -470,8 +489,9 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { // Process any pre-cache transforms content = transform(content, title.replace(/^.*\.([^.]+)$/, '$1')); } + var mimetype = fileDirEntry.getMimetype(); // Hide article while it is rendering - if (/^text\/html$/.test(fileDirEntry.getMimetype())) { + if (/^text\/html$/.test(mimetype)) { // Count CSS so we can attempt to show article before JS/images are fully loaded var cssCount = content.match(/<(?:link)[^>]+?href=["']([^"']+)[^>]+>/ig); assetsCache.cssLoading = cssCount ? cssCount.length : 0; @@ -485,7 +505,7 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { document.getElementById('searchingArticles').style.display = 'none'; } } - setItem(key, content, function (result) { + setItem(key, content, mimetype, function (result) { if (result === -1) { // Cache rejected item due to user settings } else if (result) { @@ -747,4 +767,4 @@ define(['settingsStore', 'uiUtil'], function(settingsStore, uiUtil) { replaceAssetRefsWithUri: replaceAssetRefsWithUri, verifyPermission: verifyPermission }; -}); \ No newline at end of file +});