From 1cd7804374f5fc0ee29541ab98fdafffc4c786aa Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 7 Sep 2011 17:42:17 +0200 Subject: [PATCH] [REF] websrv_lib: moved vdirs mangement code to websrv_lib (from service.http_server). The vdirs list is now a global variable, containing both secure-only and non-necessarily-secure handlers. This makes it possible to register handlers without being too tied to the multi http request handler. The goal is obviously to make it possible to serve those handlers by other means than the multi handler. bzr revid: vmt@openerp.com-20110907154217-f30nrzgvw45ga2q8 --- openerp/service/http_server.py | 50 +----------------------------- openerp/service/websrv_lib.py | 56 ++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/openerp/service/http_server.py b/openerp/service/http_server.py index 3e76c3810ef..8bf40024282 100644 --- a/openerp/service/http_server.py +++ b/openerp/service/http_server.py @@ -154,7 +154,6 @@ class BaseHttpDaemon(threading.Thread, netsvc.Server): try: self.server = ThreadedHTTPServer((interface, port), handler, proto=self._RealProto) - self.server.vdirs = [] self.server.logRequests = True self.server.timeout = self._busywait_timeout logging.getLogger("web-services").info( @@ -191,28 +190,6 @@ class BaseHttpDaemon(threading.Thread, netsvc.Server): res += ", %d threads" % (self.server.numThreads,) return res - def append_svc(self, service): - if not isinstance(service, HTTPDir): - raise Exception("Wrong class for http service") - - pos = len(self.server.vdirs) - lastpos = pos - while pos > 0: - pos -= 1 - if self.server.vdirs[pos].matches(service.path): - lastpos = pos - # we won't break here, but search all way to the top, to - # ensure there is no lesser entry that will shadow the one - # we are inserting. - self.server.vdirs.insert(lastpos, service) - - def list_services(self): - ret = [] - for svc in self.server.vdirs: - ret.append( ( svc.path, str(svc.handler)) ) - - return ret - # No need for these two classes: init_server() below can initialize correctly # directly the BaseHttpDaemon class. class HttpDaemon(BaseHttpDaemon): @@ -245,31 +222,6 @@ def init_servers(): httpsd = HttpSDaemon(tools.config.get('xmlrpcs_interface', ''), int(tools.config.get('xmlrpcs_port', 8071))) -def reg_http_service(hts, secure_only = False): - """ Register some handler to httpd. - hts must be an HTTPDir - """ - global httpd, httpsd - - if httpd and not secure_only: - httpd.append_svc(hts) - - if httpsd: - httpsd.append_svc(hts) - - if (not httpd) and (not httpsd): - logging.getLogger('httpd').warning("No httpd available to register service %s" % hts.path) - return - -def list_http_services(protocol=None): - global httpd, httpsd - if httpd and (protocol == 'http' or protocol == None): - return httpd.list_services() - elif httpsd and (protocol == 'https' or protocol == None): - return httpsd.list_services() - else: - raise Exception("Incorrect protocol or no http services") - import SimpleXMLRPCServer class XMLRPCRequestHandler(FixSendError,HttpLogHandler,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): rpc_paths = [] @@ -305,7 +257,7 @@ def init_xmlrpc(): if tools.config.get('xmlrpcs', False) \ and not tools.config.get('xmlrpc', False): # only register at the secure server - reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler), True) + reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler, secure_only=True)) logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only") class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler): diff --git a/openerp/service/websrv_lib.py b/openerp/service/websrv_lib.py index 2e098169bae..5b98714e80e 100644 --- a/openerp/service/websrv_lib.py +++ b/openerp/service/websrv_lib.py @@ -125,13 +125,17 @@ class HTTPHandler(SimpleHTTPRequestHandler): def setup(self): pass +# A list of HTTPDir. +handlers = [] + class HTTPDir: """ A dispatcher class, like a virtual folder in httpd """ - def __init__(self,path,handler, auth_provider = None): + def __init__(self, path, handler, auth_provider=None, secure_only=False): self.path = path self.handler = handler self.auth_provider = auth_provider + self.secure_only = secure_only def matches(self, request): """ Test if some request matches us. If so, return @@ -140,6 +144,42 @@ class HTTPDir: return self.path return False +def reg_http_service(service): + """ Register some handler to httpd. + hts must be an HTTPDir + """ + assert isinstance(service, HTTPDir), "Wrong class for http service" + + global handlers + pos = len(handlers) + lastpos = pos + while pos > 0: + pos -= 1 + if handlers[pos].matches(service.path): + lastpos = pos + # we won't break here, but search all way to the top, to + # ensure there is no lesser entry that will shadow the one + # we are inserting. + handlers.insert(lastpos, service) + +def list_http_services(protocol=None): + global handlers + ret = [] + for svc in handlers: + if protocol is None or protocol == 'http' or svc.secure_only: + ret.append((svc.path, str(svc.handler))) + + return ret + +def find_http_service(path, secure=False): + global handlers + for vdir in handlers: + p = vdir.matches(path) + if p == False or (vdir.secure_only and not secure): + continue + return vdir + return None + class noconnection(object): """ a class to use instead of the real connection """ @@ -408,11 +448,9 @@ class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler): return self.do_OPTIONS() return - - for vdir in self.server.vdirs: - p = vdir.matches(self.path) - if p == False: - continue + vdir = find_http_service(self.path, self.server.proto == 'HTTPS') + if vdir: + p = vdir.path npath = self.path[len(p):] if not npath.startswith('/'): npath = '/' + npath @@ -433,10 +471,8 @@ class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler): "client closed connection", self.rlpath.rstrip()) else: raise - return - # if no match: - self.send_error(404, "Path not found: %s" % self.path) - return + else: # no match: + self.send_error(404, "Path not found: %s" % self.path) def _get_ignore_body(self,fore): if not fore.headers.has_key("content-length"):