[IMP] odoo: ignore unsupported args from controller

Before this commit, call a controller defined as:

```
@http.route('/route', type='http', auth='public')
def controller_func(self, foo):
do_it()
```

and called with url like /route?foo=1&bar=2

will crash with an exception:
`TypeError: controller_func() got an unexpected keyword argument 'bar'`

Now, we remove the extra parameters if the controller doesn't support it.
This case is not uncommon, you can easily arrive in this case with utm or
debug as extra parameter.

closes odoo/odoo#33962

Signed-off-by: Christophe Simonis <chs@odoo.com>
This commit is contained in:
Jeremy Kersten
2019-06-08 13:53:57 +00:00
committed by Christophe Simonis
parent f167ae7d6e
commit 521f7d36c1
4 changed files with 65 additions and 0 deletions
+25
View File
@@ -4,6 +4,7 @@
from odoo import http
from odoo.http import request
from odoo.addons.portal.controllers.web import Home
import json
class WebsiteTest(Home):
@@ -11,3 +12,27 @@ class WebsiteTest(Home):
@http.route('/test_view', type='http', auth="public", website=True)
def test_view(self, **kw):
return request.render('test_website.test_view')
@http.route('/ignore_args/converteronly/<string:a>/', type='http', auth="public", website=True)
def test_ignore_args_converter_only(self, a):
return request.make_response(json.dumps(dict(a=a, kw=None)))
@http.route('/ignore_args/none', type='http', auth="public", website=True)
def test_ignore_args_none(self):
return request.make_response(json.dumps(dict(a=None, kw=None)))
@http.route('/ignore_args/a', type='http', auth="public", website=True)
def test_ignore_args_a(self, a):
return request.make_response(json.dumps(dict(a=a, kw=None)))
@http.route('/ignore_args/kw', type='http', auth="public", website=True)
def test_ignore_args_kw(self, a, **kw):
return request.make_response(json.dumps(dict(a=a, kw=kw)))
@http.route('/ignore_args/converter/<string:a>/', type='http', auth="public", website=True)
def test_ignore_args_converter(self, a, b='youhou', **kw):
return request.make_response(json.dumps(dict(a=a, b=b, kw=kw)))
@http.route('/ignore_args/converter/<string:a>/nokw', type='http', auth="public", website=True)
def test_ignore_args_converter_nokw(self, a, b='youhou'):
return request.make_response(json.dumps(dict(a=a, b=b)))
+1
View File
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_controller_args
from . import test_reset_views
from . import test_views_during_module_operation
@@ -0,0 +1,31 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo.tests
@odoo.tests.common.tagged('post_install', '-at_install')
class TestWebsiteControllerArgs(odoo.tests.HttpCase):
def test_crawl_args(self):
req = self.url_open('/ignore_args/converter/valueA/?b=valueB&c=valueC')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': 'valueA', 'b': 'valueB', 'kw': {'c': 'valueC'}})
req = self.url_open('/ignore_args/converter/valueA/nokw?b=valueB&c=valueC')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': 'valueA', 'b': 'valueB'})
req = self.url_open('/ignore_args/converteronly/valueA/?b=valueB&c=valueC')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': 'valueA', 'kw': None})
req = self.url_open('/ignore_args/none?a=valueA&b=valueB')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': None, 'kw': None})
req = self.url_open('/ignore_args/a?a=valueA&b=valueB')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': 'valueA', 'kw': None})
req = self.url_open('/ignore_args/kw?a=valueA&b=valueB')
self.assertEquals(req.status_code, 200)
self.assertEquals(req.json(), {'a': 'valueA', 'kw': {'b': 'valueB'}})
+8
View File
@@ -507,8 +507,16 @@ def route(route=None, **kw):
else:
routes = [route]
routing['routes'] = routes
@functools.wraps(f)
def response_wrap(*args, **kw):
# if controller cannot be called with extra args (utm, debug, ...), call endpoint ignoring them
spec = inspect.getargspec(f)
if not spec.keywords:
ignored = ['<%s=%s>' % (k, kw.pop(k)) for k in list(kw) if k not in spec.args]
if ignored:
_logger.info("<function %s.%s> called ignoring args %s" % (f.__module__, f.__name__, ', '.join(ignored)))
response = f(*args, **kw)
if isinstance(response, Response) or f.routing_type == 'json':
return response