Skip to content
Snippets Groups Projects
Commit a51ac35a authored by Julien Castiaux's avatar Julien Castiaux
Browse files

[FIX] website: 308 wrongly set on all routes

Users sometime want to rename existing controllers URL, e.g. /shop as
french /magasin. The feature is possible within Odoo thanks to 308 type
redirections that can be configured via a hidden ?debug=1-only website
menu.

Upon generating the routing-map (the structure that links URLs to
controllers), when a URL is found inside of the `website.rewrite` model,
two links (called Rules in werkzeug jargon) are registered: the new,
translated, URL is linked to the controller and the original URL is
linked to a redirection to the new URL.

For the context of this PR, it is important to note that the redirection
only applies to the very URL saved inside the `website.rewrite` model:
if a controller has multiple routes, e.g. `/shop` and `/shop/shop`, only
`/shop` is redirected to `/magasin`, `/shop/shop` is left as-is.

Without 308 redirection:

	/shop -> def shop()
	/shop/shop -> def shop()

With 308 redirection:

	website.rewrite(from_url='/shop', to_url='/magasin')
	/shop -> /magasin
	/shop/shop -> def shop()
	/magasin -> def shop()

The redirection is set on the routing dictionnary of the endpoint, this
is the dictionnary that collect the informations set via the `@route`
decorator (auth=, method=, type=, ...).

Prior to [HTTPocalypse], that dictionnary was duplicated so that the
redirection was applied on the single route endpoint that matched
the `website.rewrite` record. With [HTTPocalypse] that duplication has
been wrongly removed: all original routes redirected to the new
translated one.

Bug introduced in [HTTPocalypse]:

	website.rewrite(from_url='/shop', to_url='/magasin')
	/shop -> /magasin
	/shop/shop -> /magasin          <-- wrong
	/magasin -> def shop()

This PR fixes the problem, it makes sure that the redirection is saved
*only* on the route that matched the website.rewrite record, not the
other routes.

[HTTPocalypse]: https://github.com/odoo/odoo/pull/78857



closes odoo/odoo#133371

Signed-off-by: default avatarRomain Derie (rde) <rde@odoo.com>
parent f7649820
No related branches found
No related tags found
No related merge requests found
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import contextlib
import functools
import logging
from lxml import etree
import os
......@@ -10,8 +11,6 @@ import werkzeug
import werkzeug.routing
import werkzeug.utils
from functools import partial
import odoo
from odoo import api, models
from odoo import SUPERUSER_ID
......@@ -104,9 +103,12 @@ class Http(models.AbstractModel):
if url != url_to:
logger.debug('Redirect from %s to %s for website %s' % (url, url_to, website_id))
_slug_matching = partial(cls._slug_matching, endpoint=endpoint)
endpoint.routing['redirect_to'] = _slug_matching
yield url, endpoint # yield original redirected to new url
# duplicate the endpoint to only register the redirect_to for this specific url
redirect_endpoint = functools.partial(endpoint)
functools.update_wrapper(redirect_endpoint, endpoint)
_slug_matching = functools.partial(cls._slug_matching, endpoint=endpoint)
redirect_endpoint.routing = dict(endpoint.routing, redirect_to=_slug_matching)
yield url, redirect_endpoint # yield original redirected to new url
elif rewrite.redirect_type == '404':
logger.debug('Return 404 for %s for website %s' % (url, website_id))
continue
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment