Skip to content
Browse files

[FIX] website: language prefixed URL on website bis

Reintroduces 5324284 that was reverted because in the case of an URL
like /payment_stripe/static/src/js/stripe.js directly inside a QWeb
template, we would possibly get:


Which is not accepted by werkzeug SharedDataMiddleware we use to serve
static data in /{module_name}/static/ directories.

[WIP still need test and tests]

closes #32095
  • Loading branch information...
nle-odoo committed Mar 25, 2019
1 parent 2a89f0c commit 2d3832e366af5107eceba91b2e7aef1baa5eab93
Showing with 103 additions and 2 deletions.
  1. +1 −1 addons/http_routing/models/
  2. +8 −1 addons/website/models/
  3. +94 −0 addons/website/tests/
@@ -164,7 +164,7 @@ def is_multilang_url(local_url, langs=None):
local_url = '/'.join(spath)
# Try to match an endpoint in werkzeug's routing table
url = local_url.split('?')
url = local_url.partition('#')[0].split('?')
path = url[0]
query_string = url[1] if len(url) > 1 else None
router ='')
@@ -6,6 +6,7 @@
from odoo import models
from odoo.http import request

from odoo.addons.http_routing.models.ir_http import url_for

re_background_image = re.compile(r"(background-image\s*:\s*url\(\s*['\"]?\s*)([^)'\"]+)")

@@ -37,10 +38,16 @@ def _post_processing_att(self, tagName, atts, options):
if not website and options.get('website_id'):
website = self.env['website'].browse(options['website_id'])

if not website or not website.cdn_activated:
if not website:
return atts

name = self.URL_ATTRS.get(tagName)
if request and name and name in atts:
atts[name] = url_for(atts[name])

if not website.cdn_activated:
return atts

if name and name in atts:
atts = OrderedDict(atts)
atts[name] = website.get_cdn_url(atts[name])
@@ -3,6 +3,7 @@

import re

import odoo
from odoo import tools
from odoo.modules.module import get_module_resource
from odoo.tests.common import TransactionCase
@@ -63,3 +64,96 @@ def test_qweb_cdn(self):
"css": attachments[1].url,

class MockObject(object):
def __init__(self, *args, **kwargs):
self.__dict__ = kwargs
def __call__(self, *args, **kwargs):
return self
def __getitem__(self, index):
return self

class MockRequest(object):
""" Class with context manager mocking odoo.http.request for tests """
def __init__(self, env, website=None, context=None, multilang=True):
app = MockObject(routing={
'type': 'http',
'website': True,
'multilang': multilang,
app.get_db_router = app.bind = app.match = app
self.request = MockObject(
env=env, context=context or {}, db=None, debug=False,
website=website, httprequest=MockObject(
def __enter__(self):
return self.request
def __exit__(self, exc_type, exc_value, traceback):

class TestQwebProcessAtt(TransactionCase):
def setUp(self):
super(TestQwebProcessAtt, self).setUp() = self.env['website'].browse(1) = self.env.ref('base.lang_en') + self.env.ref('base.lang_fr') = self.env.ref('base.lang_en') = True = "http://test.cdn" = "\n".join(["^(/[a-z]{2}_[A-Z]{2})?/a$", "^/b$"])

def _test_att(self, url, expect, tag='a', attribute='href'):
self.env['ir.qweb']._post_processing_att(tag, {attribute: url}, {}),

def test_process_att_no_request(self):
# no request so no URL rewriting
self._test_att('/', {'href': '/'})
self._test_att('/en_US/', {'href': '/en_US/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
# no URL rewritting for CDN
self._test_att('/a', {'href': '/a'})

def test_process_att_no_website(self):
with MockRequest(self.env) as request:
# no website so URL rewriting
self._test_att('/', {'href': '/'})
self._test_att('/en_US/', {'href': '/en_US/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
# no URL rewritting for CDN
self._test_att('/a', {'href': '/a'})

def test_process_att_monolang_route(self):
with MockRequest(self.env,, multilang=False) as request:
# lang not changed in URL but CDN enabled
self._test_att('/a', {'href': 'http://test.cdn/a'})
self._test_att('/en_US/a', {'href': 'http://test.cdn/en_US/a'})
self._test_att('/b', {'href': 'http://test.cdn/b'})
self._test_att('/en_US/b', {'href': '/en_US/b'})

def test_process_att_no_request_lang(self):
with MockRequest(self.env, as request:
self._test_att('/', {'href': '/'})
self._test_att('/en_US/', {'href': '/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})

def test_process_att_with_request_lang(self):
with MockRequest(self.env,, context={'lang': 'fr_FR'}) as request:
self._test_att('/', {'href': '/fr_FR/'})
self._test_att('/en_US/', {'href': '/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})

def test_process_att_matching_cdn_and_lang(self):
with MockRequest(self.env, as request:
# lang prefix is added before CDN
self._test_att('/a', {'href': 'http://test.cdn/a'})
self._test_att('/en_US/a', {'href': 'http://test.cdn/a'})
self._test_att('/fr_FR/a', {'href': 'http://test.cdn/fr_FR/a'})
self._test_att('/b', {'href': 'http://test.cdn/b'})
self._test_att('/en_US/b', {'href': 'http://test.cdn/b'})
self._test_att('/fr_FR/b', {'href': '/fr_FR/b'})

0 comments on commit 2d3832e

Please sign in to comment.
You can’t perform that action at this time.