Skip to content

Commit

Permalink
[FIX] website: language prefixed URL on website
Browse files Browse the repository at this point in the history
In 10.0 and before, if we were eg. on website page /fr_FR/contact, if
`fr_FR` language (french) is installed and not the default website
language we would have all URL towards translated content (route with
multilang=True) prefixed with /fr_FR/ (the language code).

With 9cd982b some improvments were done to CDN but this also breaks
language prefixing, so this cause an unecessary redirect:

- we are on /fr_FR/contact and click on "Shop"
- we go to /shop
- odoo redirects US /fr_FR/shop

With this PR, URLs are prefixed with language once again.

note: the added test is hackish but the function tested depends on a lot
of odoo.http things that are hard to use for test (request.render,
request.context, request.httpreqest).

opw-1922051
closes #31792

Signed-off-by: Christophe Simonis <chs@odoo.com>
  • Loading branch information
nle-odoo committed Mar 22, 2019
1 parent 3a0bedd commit 5324284
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 1 deletion.
9 changes: 8 additions & 1 deletion addons/website/models/ir_qweb.py
Expand Up @@ -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*)([^)'\"]+)")

Expand Down Expand Up @@ -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])
Expand Down
94 changes: 94 additions & 0 deletions addons/website/tests/test_qweb.py
Expand Up @@ -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
Expand Down Expand Up @@ -63,3 +64,96 @@ def test_qweb_cdn(self):
"css": attachments[1].url,
"user_id": demo.id,
}).encode('utf8'))

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(
path='/hello/',
app=app
)
)
odoo.http._request_stack.push(self.request)
def __enter__(self):
return self.request
def __exit__(self, exc_type, exc_value, traceback):
odoo.http._request_stack.pop()

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

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

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, website=self.website, 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, self.website) as request:

This comment has been minimized.

Copy link
@JKE-be

JKE-be Apr 11, 2019

Contributor
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, self.website, 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, self.website) 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 5324284

Please sign in to comment.