[IMP] base, http_routing, website: allow custom routing rule
After this commit, you will be able (in technical mode) to update the url for the python controllers. Eg. You can now rename /shop in /garden and /shop/product/ in /garden/vegetable/ Most of urls will be replaced at fly in the renderd qweb, with the function url_for but all old urls will keep available. So if you access url /shop you will be automatically redirected to /garden (308 Permanent Redirect). As for cdn and other post-process of att, the automatically replacement in the rendered qweb is only done when you will be not website editor. But the new dispatch of URL will be applied in all cases. For developper, since it is Permanent Redirect, don't forget to clear cache or open chrome debug tool (with option 'Disable cache while DevTools is Open) to see your lasts changes. closes odoo/odoo#36555 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
@@ -87,8 +87,12 @@ class IrHttp(models.AbstractModel):
|
||||
return {'model': ModelConverter, 'models': ModelsConverter, 'int': SignedIntConverter}
|
||||
|
||||
@classmethod
|
||||
def _find_handler(cls, return_rule=False):
|
||||
return cls.routing_map().bind_to_environ(request.httprequest.environ).match(return_rule=return_rule)
|
||||
def _match(cls, path_info, key=None):
|
||||
return cls.routing_map(key=key).bind('').match(
|
||||
return_rule=True,
|
||||
method=request.httprequest.method,
|
||||
path_info=path_info
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _auth_method_user(cls):
|
||||
@@ -208,7 +212,7 @@ class IrHttp(models.AbstractModel):
|
||||
|
||||
# locate the controller method
|
||||
try:
|
||||
rule, arguments = cls._find_handler(return_rule=True)
|
||||
rule, arguments = cls._match(request.httprequest.path)
|
||||
func = rule.endpoint
|
||||
except werkzeug.exceptions.NotFound as e:
|
||||
return cls._handle_exception(e)
|
||||
@@ -245,24 +249,37 @@ class IrHttp(models.AbstractModel):
|
||||
return cls._handle_exception(werkzeug.exceptions.NotFound())
|
||||
|
||||
@classmethod
|
||||
def routing_map(cls):
|
||||
def _generate_routing_rules(cls, modules, converters):
|
||||
return http._generate_routing_rules(modules, False, converters)
|
||||
|
||||
@classmethod
|
||||
def routing_map(cls, key=None):
|
||||
if not hasattr(cls, '_routing_map'):
|
||||
_logger.info("Generating routing map")
|
||||
installed = request.registry._init_modules - {'web'}
|
||||
cls._routing_map = {}
|
||||
cls._rewrite_len = {}
|
||||
if key not in cls._routing_map:
|
||||
_logger.info("Generating routing map for key %s" % str(key))
|
||||
installed = request.registry._init_modules | set(odoo.conf.server_wide_modules)
|
||||
if tools.config['test_enable'] and odoo.modules.module.current_test:
|
||||
installed.add(odoo.modules.module.current_test)
|
||||
mods = [''] + odoo.conf.server_wide_modules + sorted(installed)
|
||||
mods = sorted(installed)
|
||||
# Note : when routing map is generated, we put it on the class `cls`
|
||||
# to make it available for all instance. Since `env` create an new instance
|
||||
# of the model, each instance will regenared its own routing map and thus
|
||||
# regenerate its EndPoint. The routing map should be static.
|
||||
cls._routing_map = http.routing_map(mods, False, converters=cls._get_converters())
|
||||
return cls._routing_map
|
||||
routing_map = werkzeug.routing.Map(strict_slashes=False, converters=cls._get_converters())
|
||||
for url, endpoint, routing in cls._generate_routing_rules(mods, converters=cls._get_converters()):
|
||||
xtra_keys = 'defaults subdomain build_only strict_slashes redirect_to alias host'.split()
|
||||
kw = {k: routing[k] for k in xtra_keys if k in routing}
|
||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods'], **kw))
|
||||
cls._routing_map[key] = routing_map
|
||||
return cls._routing_map[key]
|
||||
|
||||
@classmethod
|
||||
def _clear_routing_map(cls):
|
||||
if hasattr(cls, '_routing_map'):
|
||||
del cls._routing_map
|
||||
cls._routing_map = {}
|
||||
_logger.debug("Clear routing map")
|
||||
|
||||
#------------------------------------------------------
|
||||
# Binary server
|
||||
@@ -337,8 +354,6 @@ class IrHttp(models.AbstractModel):
|
||||
status = 301
|
||||
content = record.url
|
||||
|
||||
|
||||
|
||||
return status, content, filename, mimetype, filehash
|
||||
|
||||
def _binary_record_content(
|
||||
|
||||
+6
-12
@@ -908,9 +908,8 @@ class EndPoint(object):
|
||||
def __call__(self, *args, **kw):
|
||||
return self.method(*args, **kw)
|
||||
|
||||
def routing_map(modules, nodb_only, converters=None):
|
||||
routing_map = werkzeug.routing.Map(strict_slashes=False, converters=converters)
|
||||
|
||||
def _generate_routing_rules(modules, nodb_only, converters=None):
|
||||
def get_subclasses(klass):
|
||||
def valid(c):
|
||||
return c.__module__.startswith('odoo.addons.') and c.__module__.split(".")[2] in modules
|
||||
@@ -949,16 +948,8 @@ def routing_map(modules, nodb_only, converters=None):
|
||||
assert routing['routes'], "Method %r has not route defined" % mv
|
||||
endpoint = EndPoint(mv, routing)
|
||||
for url in routing['routes']:
|
||||
if routing.get("combine", False):
|
||||
# deprecated v7 declaration
|
||||
url = o._cp_path.rstrip('/') + '/' + url.lstrip('/')
|
||||
if url.endswith("/") and len(url) > 1:
|
||||
url = url[: -1]
|
||||
yield (url, endpoint, routing)
|
||||
|
||||
xtra_keys = 'defaults subdomain build_only strict_slashes redirect_to alias host'.split()
|
||||
kw = {k: routing[k] for k in xtra_keys if k in routing}
|
||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods'], **kw))
|
||||
return routing_map
|
||||
|
||||
#----------------------------------------------------------
|
||||
# HTTP Sessions
|
||||
@@ -1276,7 +1267,10 @@ class Root(object):
|
||||
@lazy_property
|
||||
def nodb_routing_map(self):
|
||||
_logger.info("Generating nondb routing")
|
||||
return routing_map([''] + odoo.conf.server_wide_modules, True)
|
||||
routing_map = werkzeug.routing.Map(strict_slashes=False, converters=None)
|
||||
for url, endpoint, routing in odoo.http._generate_routing_rules([''] + odoo.conf.server_wide_modules, True):
|
||||
routing_map.add(werkzeug.routing.Rule(url, endpoint=endpoint, methods=routing['methods']))
|
||||
return routing_map
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
""" Handle a WSGI request
|
||||
|
||||
Reference in New Issue
Block a user