diff options
| author | Jeremy Kersten <jke@odoo.com> | 2019-09-12 09:45:11 +0000 |
|---|---|---|
| committer | Jeremy Kersten <jke@odoo.com> | 2019-09-30 13:58:14 +0000 |
| commit | be8fc2296b3822baffe0bc68cb4b7efdfe53fa91 (patch) | |
| tree | 08f0f825cfe2ffa652557f244f36880149d2f585 /odoo | |
| parent | b6b42ef73f4c517d9b7bc2da4909c13d7fe8f2c6 (diff) | |
[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>
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/base/models/ir_http.py | 39 | ||||
| -rw-r--r-- | odoo/http.py | 18 |
2 files changed, 33 insertions, 24 deletions
diff --git a/odoo/addons/base/models/ir_http.py b/odoo/addons/base/models/ir_http.py index cc76a8d0ff9..f2c87db5fa4 100644 --- a/odoo/addons/base/models/ir_http.py +++ b/odoo/addons/base/models/ir_http.py @@ -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( diff --git a/odoo/http.py b/odoo/http.py index 94445401801..721746ee7ce 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -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 |
