Commit 9a80c31d authored by Romain Courteaud's avatar Romain Courteaud Committed by Xiaowu Zhang

erp5_web: force redirection on website using a service worker

Delete the content of the cache storage (used by erp5js), unregister the service worker and force the browser to reload.
parent 1c2ab1ec
...@@ -95,6 +95,7 @@ ...@@ -95,6 +95,7 @@
<list> <list>
<string>my_redirect_domain</string> <string>my_redirect_domain</string>
<string>my_use_moved_temporarily</string> <string>my_use_moved_temporarily</string>
<string>my_configuration_service_worker_url</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_configuration_service_worker_url</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_reference</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Service Worker URL</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -20,8 +20,56 @@ try: ...@@ -20,8 +20,56 @@ try:
source_path = REQUEST.other["source_path"] source_path = REQUEST.other["source_path"]
redirect_url = "/".join([redirect_url, source_path]) redirect_url = "/".join([redirect_url, source_path])
except(KeyError): except(KeyError):
source_path = None
redirect_url = redirect_url + "/" redirect_url = redirect_url + "/"
service_worker_to_unregister = context.getLayoutProperty("configuration_service_worker_url")
if (service_worker_to_unregister) and (source_path == service_worker_to_unregister) and (not query_string):
# Do not redirect the service worker URL
# instead, unregister it and force all clients to reload themself
response = REQUEST.RESPONSE
response.setHeader('Content-Type', 'application/javascript')
return """/*jslint indent: 2*/
/*global self, Promise, caches*/
(function (self, Promise, caches) {
"use strict";
self.addEventListener('install', function (event) {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function (event) {
event.waitUntil(
caches
.keys()
.then(function (keys) {
return Promise.all(
keys
.map(function (key) {
return caches.delete(key);
})
);
})
.then(function () {
return self.registration.unregister();
})
.then(function () {
return self.clients.matchAll({type: 'window'});
})
.then(function (client_list) {
var i,
promise_list = [];
for (i = 0; i < client_list.length; i += 1) {
promise_list.push(client_list[i].navigate(client_list[i].url));
}
return Promise.all(promise_list);
})
);
});
}(self, Promise, caches));
"""
if query_string: if query_string:
redirect_url = '?'.join([redirect_url, query_string]) redirect_url = '?'.join([redirect_url, query_string])
if redirect_url.find(INDEX) > -1 and not redirect_url.endswith(INDEX): if redirect_url.find(INDEX) > -1 and not redirect_url.endswith(INDEX):
......
...@@ -73,12 +73,15 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase): ...@@ -73,12 +73,15 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase):
self.tic() self.tic()
return website return website
def runTestRedirect(self, source_path, expected_failure=None, use_moved_temporarily=None, **kw): def runTestRedirect(self, source_path, expected_failure=None,
use_moved_temporarily=None,
configuration_service_worker_url=None, **kw):
""" """
Redirect to backend configuration redirect_domain Redirect to backend configuration redirect_domain
""" """
# create website and websection # create website and websection
website = self.setupWebSite(use_moved_temporarily=use_moved_temporarily) website = self.setupWebSite(use_moved_temporarily=use_moved_temporarily,
configuration_service_worker_url=configuration_service_worker_url)
absolute_url = website.absolute_url() absolute_url = website.absolute_url()
...@@ -119,8 +122,20 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase): ...@@ -119,8 +122,20 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase):
url=url_to_check url=url_to_check
) )
response = connection.getresponse() response = connection.getresponse()
response_body = response.read()
if (source_path == configuration_service_worker_url):
# Test service worker URL
self.assertEquals(response.status, httplib.OK, '%s: %s' % (response.status, url_to_check))
self.assertEquals(response.getheader('Content-Type'), 'application/javascript')
self.assertTrue('self.registration.unregister()' in response_body,
response_body)
else:
self.assertEquals(response.status, status_to_assert, '%s: %s' % (response.status, url_to_check)) self.assertEquals(response.status, status_to_assert, '%s: %s' % (response.status, url_to_check))
self.assertEquals(response.getheader(LOCATION), redirect_location) self.assertEquals(response.getheader(LOCATION), redirect_location)
self.assertEquals(response.getheader('Content-Type'), 'text/plain; charset=utf-8')
self.assertEquals(response_body, redirect_location)
############################################################################## ##############################################################################
...@@ -191,6 +206,10 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase): ...@@ -191,6 +206,10 @@ class TestStaticWebSiteRedirection(ERP5TypeTestCase):
def test_302queryStringRedirectFolderDeepNested(self): def test_302queryStringRedirectFolderDeepNested(self):
self.runTestRedirect("foo/bar/baz?baz=bam&cous=cous&amp;the=end", use_moved_temporarily=1) self.runTestRedirect("foo/bar/baz?baz=bam&cous=cous&amp;the=end", use_moved_temporarily=1)
def test_unregisterServiceWorker(self):
worker_url = 'worker.js'
self.runTestRedirect(worker_url,
configuration_service_worker_url=worker_url)
class TestStaticWebSectionRedirection(TestStaticWebSiteRedirection): class TestStaticWebSectionRedirection(TestStaticWebSiteRedirection):
......
...@@ -6,12 +6,6 @@ ...@@ -6,12 +6,6 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>testStaticWebSiteRedirection</string> </value> <value> <string>testStaticWebSiteRedirection</string> </value>
...@@ -43,11 +37,7 @@ ...@@ -43,11 +37,7 @@
<item> <item>
<key> <string>text_content_warning_message</string> </key> <key> <string>text_content_warning_message</string> </key>
<value> <value>
<tuple> <tuple/>
<string>W: 91, 28: Unused variable \'api_path\' (unused-variable)</string>
<string>W: 91, 16: Unused variable \'api_netloc\' (unused-variable)</string>
<string>W: 91, 4: Unused variable \'api_scheme\' (unused-variable)</string>
</tuple>
</value> </value>
</item> </item>
<item> <item>
...@@ -57,28 +47,13 @@ ...@@ -57,28 +47,13 @@
<item> <item>
<key> <string>workflow_history</string> </key> <key> <string>workflow_history</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="PersistentMapping" module="Persistence.mapping"/> <global name="PersistentMapping" module="Persistence.mapping"/>
</pickle> </pickle>
...@@ -91,7 +66,7 @@ ...@@ -91,7 +66,7 @@
<item> <item>
<key> <string>component_validation_workflow</string> </key> <key> <string>component_validation_workflow</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
...@@ -100,7 +75,7 @@ ...@@ -100,7 +75,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment