diff --git a/src/main/declarative-net-engine.js b/src/main/declarative-net-engine.js index ad46fc7..fff4c60 100644 --- a/src/main/declarative-net-engine.js +++ b/src/main/declarative-net-engine.js @@ -3,7 +3,7 @@ import ServiceWorkerComponent from './service-worker-component'; class BaseRule { constructor() { - this.priority = 1; + this.priority = 100; } hashCode() { @@ -106,10 +106,54 @@ class BasicAuthenticationHeaderRule extends BaseRule { } } +class CacheControlHeaderRule extends BaseRule { + constructor(url, cacheControlHeader) { + super(); + + // Set properties + this.cacheControlHeader = cacheControlHeader; + this.url = url; + + // Bind methods + Object.getOwnPropertyNames(Object.getPrototypeOf(this)) + .filter((prop) => typeof this[prop] === 'function' && prop !== 'constructor') + .forEach((method) => { + this[method] = this[method].bind(this); + }); + } + + // eslint-disable-next-line class-methods-use-this + key() { + return `cacheControlHeader-${this.url}`; + } + + toJson(priority = 1) { + return { + id: this.hashCode(), + priority, + condition: { + urlFilter: this.url.toString(), + }, + action: { + type: 'modifyHeaders', + requestHeaders: [ + { + header: 'Cache-Control', + operation: 'set', + value: this.cacheControlHeader, + }, + ], + }, + }; + } +} + class RedirectRule extends BaseRule { constructor(from, to) { super(); + this.priority -= 10; + // Set properties this.from = from; this.to = to; @@ -144,7 +188,6 @@ class RedirectRule extends BaseRule { }, }, }, - cacheControl: 'no-cache, no-store, must-revalidate' }; return json; } @@ -321,5 +364,5 @@ class DeclarativeNetEngine extends ServiceWorkerComponent { } export default { - BasicAuthenticationHeaderRule, CookieHeaderRule, RedirectRule, DeclarativeNetEngine, + BasicAuthenticationHeaderRule, CookieHeaderRule, CacheControlHeaderRule, RedirectRule, DeclarativeNetEngine, }; diff --git a/src/main/designer-live-preview.js b/src/main/designer-live-preview.js index 3f83401..2650215 100644 --- a/src/main/designer-live-preview.js +++ b/src/main/designer-live-preview.js @@ -23,6 +23,7 @@ import ServiceWorkerComponent from './service-worker-component'; const BasicAuthenticationHeaderRule = DeclarativeNetComponents.BasicAuthenticationHeaderRule; const CookieHeaderRule = DeclarativeNetComponents.CookieHeaderRule; +const CacheControlHeaderRule = DeclarativeNetComponents.CacheControlHeaderRule; const RedirectRule = DeclarativeNetComponents.RedirectRule; class DesignerLivePreview extends ServiceWorkerComponent { @@ -54,6 +55,10 @@ class DesignerLivePreview extends ServiceWorkerComponent { .declarativeNetEngine.push(new CookieHeaderRule(domain, cookieHeader))); } + pushNoCacheControlHeaderOf(url) { + return this.worker.declarativeNetEngine.push(new CacheControlHeaderRule(url, 'no-cache, no-store, must-revalidate')); + } + pushRedirectionsOf(json, credentials = undefined, runtimeInfo = this.worker.serverConnector.runtimeInfo) { const { serverUrl: serverLocation, connectRegistration: { connectUrl: connectLocation } } = runtimeInfo; const serverUrl = new URL(serverLocation); @@ -74,10 +79,14 @@ class DesignerLivePreview extends ServiceWorkerComponent { const resourceConnectUrl = new URL(json[basePath][resourcePath]); const updatedResourceConnectUrl = new URL(`${resourceConnectUrl.pathname}${resourceConnectUrl.search}${resourceConnectUrl.hash}`, connectUrl); + const subPromises = [ + this.pushNoCacheControlHeaderOf(resourceConnectUrl), + this.pushRedirection(resourceNuxeoUrl, updatedResourceConnectUrl), + ]; if (credentials) { - this.pushAuthentication(updatedResourceConnectUrl, credentials); + subPromises.push(this.pushAuthentication(updatedResourceConnectUrl, credentials)); } - return this.pushRedirection(resourceNuxeoUrl, updatedResourceConnectUrl); + return Promise.all(subPromises); }); }); @@ -151,10 +160,10 @@ class DesignerLivePreview extends ServiceWorkerComponent { return this.worker.connectLocator .asRegistration() .then(({ location, credentials }) => { - const url = new URL(`studio/v2/project/${projectName}/workspace/ws.resources`, location); - return { url, credentials }; + const workspaceUrl = new URL(`studio/v2/project/${projectName}/workspace/ws.resources`, location); + return { workspaceUrl, credentials }; }) - .then(({ url: workspaceUrl, credentials }) => fetch(workspaceUrl, { + .then(({ workspaceUrl, credentials }) => fetch(workspaceUrl, { credentials: 'include', }) .then((response) => ({ workspaceUrl, response, credentials }))) @@ -195,6 +204,7 @@ class DesignerLivePreview extends ServiceWorkerComponent { .then(() => this.pushCookieHeaderOf(workspaceUrl)) .then(() => this.pushRedirectionsOf(json, credentials)) .then(() => this.worker.declarativeNetEngine.flush()) + .then(() => this.worker.tabNavigationHandler.reloadServerTab({ byPassCache: true })) .then((undo) => this.undoByProjectNames.set(projectName, undo)) .then(() => true)); } diff --git a/src/main/tab-navigation-handler.js b/src/main/tab-navigation-handler.js index f15895a..fedf6bb 100644 --- a/src/main/tab-navigation-handler.js +++ b/src/main/tab-navigation-handler.js @@ -51,44 +51,42 @@ class TabNavigationHandler extends ServiceWorkerComponent { .then(([tabInfo]) => tabInfo); } - reloadServerTab(context = { - rootUrl: this.worker.serverConnector.serverUrl, - tabInfo: this.tabInfo - }, maxAttempts = 1, waitingTime = 4000, hasReloaded = false) { - return Promise.resolve(context) - .then(({ rootUrl, tabInfo }) => { - if (!tabInfo) { - throw new Error('No nuxeo server tab info selected'); - } - return { rootUrl, tabInfo }; - }).then(({ rootUrl }) => { - const runningStatusUrl = `${rootUrl}/runningstatus`; - let attempts = 0; - const checkStatus = () => { - attempts += 1; - if (attempts > maxAttempts) { - throw new Error(`Maximum number of attempts reached on ${rootUrl}...`); + reloadServerTab(overrideOptions = {}) { + const defaultOptions = { + rootUrl: this.worker.serverConnector.serverUrl, + tabInfo: this.tabInfo, + maxAttempts: 1, + waitingTime: 4000, + bypassCache: false + }; + const { + rootUrl, tabInfo, maxAttempts, waitingTime, bypassCache + } = { ...defaultOptions, ...overrideOptions }; + if (!tabInfo) { + return Promise.reject(new Error('No nuxeo server tab info selected')); + } + const runningStatusUrl = `${rootUrl}/runningstatus`; + let attempts = 0; + const checkStatus = () => { + attempts += 1; + if (attempts > maxAttempts) { + throw new Error(`Maximum number of attempts reached on ${rootUrl}...`); + } + return fetch(runningStatusUrl) + .then((response) => { + if (!response.ok) { + // If the status page is not available, check again after a delay + return new Promise((resolve) => setTimeout(resolve, waitingTime)) + .then(checkStatus); } - return fetch(runningStatusUrl) - .then((response) => { - if (!response.ok) { - // If the status page is not available, check again after a delay - return new Promise((resolve) => setTimeout(resolve, waitingTime)) - .then(checkStatus); - } - // Reload the tab only if it has not been reloaded yet - if (!hasReloaded) { - // chrome.tabs.reload(tabInfo.id); - hasReloaded = true; // Update the flag to prevent further reloads - } - return response; - }) - .catch(() => new Promise((resolve) => setTimeout(resolve, waitingTime)) - .then(checkStatus)); - }; - // Start checking the status - return checkStatus(); - }); + chrome.tabs.reload(tabInfo.id, { bypassCache }); + return response; + }) + .catch(() => new Promise((resolve) => setTimeout(resolve, waitingTime)) + .then(checkStatus)); + }; + // Start checking the status + return checkStatus(); } updateServerTab(inputUrl, appendNuxeBasePath = false) {