diff options
Diffstat (limited to 'addons/web/http.py')
| -rw-r--r-- | addons/web/http.py | 136 |
1 files changed, 67 insertions, 69 deletions
diff --git a/addons/web/http.py b/addons/web/http.py index ccd1125fa22..7bad66cb7c4 100644 --- a/addons/web/http.py +++ b/addons/web/http.py @@ -21,6 +21,7 @@ import urlparse import uuid import errno import re +import warnings import babel.core import simplejson @@ -35,7 +36,7 @@ import urllib import urllib2 import openerp -import openerp.service.security as security +from openerp.service import security, model as service_model from openerp.tools import config import inspect @@ -177,8 +178,19 @@ class WebRequest(object): self.disable_db = True self.uid = None + @property + def debug(self): + return 'debug' in self.httprequest.args + + @contextlib.contextmanager + def registry_cr(self): + warnings.warn('please use request.registry and request.cr directly', DeprecationWarning) + yield (self.registry, self.cr) + def auth_method_user(): request.uid = request.session.uid + if not request.uid: + raise SessionExpiredException("Session expired") def auth_method_admin(): if not request.db: @@ -382,10 +394,10 @@ def jsonrequest(f): Use the ``route()`` decorator instead. """ f.combine = True - base = f.__name__ + base = f.__name__.lstrip('/') if f.__name__ == "index": base = "" - return route([base, os.path.join(base, "<path:_ignored_path>")], type="json", auth="user")(f) + return route([base, base + "/<path:_ignored_path>"], type="json", auth="user")(f) class HttpRequest(WebRequest): """ Regular GET/POST request @@ -395,21 +407,12 @@ class HttpRequest(WebRequest): def __init__(self, *args): super(HttpRequest, self).__init__(*args) params = dict(self.httprequest.args) - ex = set(["session_id"]) - for k in params.keys(): - if k in ex: - del params[k] params.update(self.httprequest.form) params.update(self.httprequest.files) + params.pop('session_id', None) self.params = params def dispatch(self): - akw = {} - for key, value in self.httprequest.args.iteritems(): - if isinstance(value, basestring) and len(value) < 1024: - akw[key] = value - else: - akw[key] = type(value) try: r = self._call_function(**self.params) except werkzeug.exceptions.HTTPException, e: @@ -460,10 +463,10 @@ def httprequest(f): Use the ``route()`` decorator instead. """ f.combine = True - base = f.__name__ + base = f.__name__.lstrip('/') if f.__name__ == "index": base = "" - return route([base, os.path.join(base, "<path:_ignored_path>")], type="http", auth="user")(f) + return route([base, base + "/<path:_ignored_path>"], type="http", auth="user")(f) #---------------------------------------------------------- # Local storage of requests @@ -472,18 +475,20 @@ from werkzeug.local import LocalStack _request_stack = LocalStack() -def set_request(request): - class with_obj(object): - def __enter__(self): - _request_stack.push(request) - def __exit__(self, *args): - _request_stack.pop() - return with_obj() +@contextlib.contextmanager +def set_request(req): + _request_stack.push(req) + try: + yield + finally: + _request_stack.pop() + + +request = _request_stack() """ A global proxy that always redirect to the current request object. """ -request = _request_stack() #---------------------------------------------------------- # Controller registration with a metaclass @@ -496,16 +501,13 @@ class ControllerType(type): def __init__(cls, name, bases, attrs): super(ControllerType, cls).__init__(name, bases, attrs) - # create wrappers for old-style methods with req as first argument - cls._methods_wrapper = {} + # flag old-style methods with req as first argument for k, v in attrs.items(): if inspect.isfunction(v): spec = inspect.getargspec(v) first_arg = spec.args[1] if len(spec.args) >= 2 else None if first_arg in ["req", "request"]: - def build_new(nv): - return lambda self, *args, **kwargs: nv(self, request, *args, **kwargs) - cls._methods_wrapper[k] = build_new(v) + v._first_arg_is_req = True # store the controller in the controllers list name_class = ("%s.%s" % (cls.__module__, cls.__name__), cls) @@ -514,7 +516,6 @@ class ControllerType(type): return # we want to know all modules that have controllers module = class_path[2] - controllers_per_module.setdefault(module, []) # but we only store controllers directly inheriting from Controller if not "Controller" in globals() or not Controller in bases: return @@ -523,12 +524,6 @@ class ControllerType(type): class Controller(object): __metaclass__ = ControllerType - def get_wrapped_method(self, name): - if name in self.__class__._methods_wrapper: - return functools.partial(self.__class__._methods_wrapper[name], self) - else: - return getattr(self, name) - ############################# # OpenERP Sessions # ############################# @@ -865,8 +860,7 @@ class Root(object): self.addons = {} self.statics = {} - self.db_routers = {} - self.db_routers_lock = threading.Lock() + self.no_db_router = None self.load_addons() @@ -915,10 +909,7 @@ class Root(object): db = request.db if db: - updated = openerp.modules.registry.RegistryManager.check_registry_signaling(db) - if updated: - with self.db_routers_lock: - del self.db_routers[db] + openerp.modules.registry.RegistryManager.check_registry_signaling(db) with set_request(request): self.find_handler() @@ -983,7 +974,7 @@ class Root(object): def _build_router(self, db): _logger.info("Generating routing configuration for database %s" % db) - routing_map = routing.Map() + routing_map = routing.Map(strict_slashes=False) def gen(modules, nodb_only): for module in modules: @@ -991,8 +982,8 @@ class Root(object): cls = v[1] subclasses = cls.__subclasses__() - subclasses = [c for c in subclasses if c.__module__.split(".")[:2] == ["openerp", "addons"] and \ - cls.__module__.split(".")[2] in modules] + subclasses = [c for c in subclasses if c.__module__.startswith('openerp.addons.') and + c.__module__.split(".")[2] in modules] if subclasses: name = "%s (extended by %s)" % (cls.__name__, ', '.join(sub.__name__ for sub in subclasses)) cls = type(name, tuple(reversed(subclasses)), {}) @@ -1001,17 +992,15 @@ class Root(object): members = inspect.getmembers(o) for mk, mv in members: if inspect.ismethod(mv) and getattr(mv, 'exposed', False) and \ - nodb_only == (getattr(mv, "auth", None) == "none"): - function = (o.get_wrapped_method(mk), mv) + nodb_only == (getattr(mv, "auth", "none") == "none"): for url in mv.routes: if getattr(mv, "combine", False): - url = os.path.join(o._cp_path, url) + url = o._cp_path.rstrip('/') + '/' + url.lstrip('/') if url.endswith("/") and len(url) > 1: url = url[: -1] - routing_map.add(routing.Rule(url, endpoint=function)) + routing_map.add(routing.Rule(url, endpoint=mv)) - modules_set = set(controllers_per_module.keys()) - modules_set -= set("web") + modules_set = set(controllers_per_module.keys()) - set(['web']) # building all none methods gen(["web"] + sorted(modules_set), True) if not db: @@ -1020,22 +1009,26 @@ class Root(object): registry = openerp.modules.registry.RegistryManager.get(db) with registry.cursor() as cr: m = registry.get('ir.module.module') - ids = m.search(cr, openerp.SUPERUSER_ID, [('state','=','installed')]) - installed = set([x['name'] for x in m.read(cr, 1, ids, ['name'])]) - modules_set = modules_set.intersection(set(installed)) - modules = ["web"] + sorted(modules_set) + ids = m.search(cr, openerp.SUPERUSER_ID, [('state', '=', 'installed'), ('name', '!=', 'web')]) + installed = set(x['name'] for x in m.read(cr, 1, ids, ['name'])) + modules_set = modules_set & installed + # building all other methods gen(["web"] + sorted(modules_set), False) return routing_map def get_db_router(self, db): - with self.db_routers_lock: - router = self.db_routers.get(db) + if db is None: + router = self.no_db_router + else: + router = getattr(openerp.modules.registry.RegistryManager.get(db), "werkzeug_http_router", None) if not router: router = self._build_router(db) - with self.db_routers_lock: - self.db_routers[db] = router + if db is None: + self.no_db_router = router + else: + openerp.modules.registry.RegistryManager.get(db).werkzeug_http_router = router return router def find_handler(self): @@ -1044,17 +1037,25 @@ class Root(object): """ path = request.httprequest.path urls = self.get_db_router(request.db).bind("") - matched, arguments = urls.match(path) + func, arguments = urls.match(path) arguments = dict([(k, v) for k, v in arguments.items() if not k.startswith("_ignored_")]) - func, original = matched + + @service_model.check + def checked_call(dbname, *a, **kw): + return func(*a, **kw) def nfunc(*args, **kwargs): kwargs.update(arguments) + if getattr(func, '_first_arg_is_req', False): + args = (request,) + args + + if request.db: + return checked_call(request.db, *args, **kwargs) return func(*args, **kwargs) request.func = nfunc - request.auth_method = getattr(original, "auth", "user") - request.func_request_type = original.exposed + request.auth_method = getattr(func, "auth", "user") + request.func_request_type = func.exposed root = None @@ -1084,17 +1085,14 @@ def db_monodb(httprequest=None): dbs = db_list(True, httprequest) - # 1 try the db already in the session + # try the db already in the session db_session = httprequest.session.db if db_session in dbs: return db_session - # 2 if there is only one db in the db filters, take it - if len(dbs) == 1: - return dbs[0] - - # 3 if there are multiple dbs, take the first one only if we can list them - if len(dbs) > 1 and config['list_db']: + # if dbfilters was specified when launching the server and there is + # only one possible db, we take that one + if openerp.tools.config['dbfilter'] != ".*" and len(dbs) == 1: return dbs[0] return None |
