X-Git-Url: http://git.inspyration.org/?a=blobdiff_plain;f=openerp%2Fservice%2Fwsgi_server.py;h=e9e391d1906a13fc138e905559f5ae463849c4e3;hb=3ee1923ca31fd6e65191462596d5c537310ca976;hp=00ad54575b171ebb2673af86de35e799668a1716;hpb=7137bb0b53f38d1a600d47d0b7b9ec83a824337f;p=odoo%2Fodoo.git diff --git a/openerp/service/wsgi_server.py b/openerp/service/wsgi_server.py index 00ad545..e9e391d 100644 --- a/openerp/service/wsgi_server.py +++ b/openerp/service/wsgi_server.py @@ -34,6 +34,7 @@ import errno import logging import os import signal +import socket import sys import threading import traceback @@ -90,10 +91,10 @@ def xmlrpc_return(start_response, service, method, params, legacy_exceptions=Fal return [response] def xmlrpc_handle_exception(e): - if isinstance(e, openerp.osv.osv.except_osv): # legacy + if isinstance(e, openerp.osv.orm.except_orm): # legacy fault = xmlrpclib.Fault(RPC_FAULT_CODE_WARNING, openerp.tools.ustr(e.value)) response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) - elif isinstance(e, openerp.exceptions.Warning): + elif isinstance(e, openerp.exceptions.Warning) or isinstance(e, openerp.exceptions.RedirectWarning): fault = xmlrpclib.Fault(RPC_FAULT_CODE_WARNING, str(e)) response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) elif isinstance (e, openerp.exceptions.AccessError): @@ -123,7 +124,7 @@ def xmlrpc_handle_exception(e): return response def xmlrpc_handle_exception_legacy(e): - if isinstance(e, openerp.osv.osv.except_osv): + if isinstance(e, openerp.osv.orm.except_orm): fault = xmlrpclib.Fault('warning -- ' + e.name + '\n\n' + e.value, '') response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) elif isinstance(e, openerp.exceptions.Warning): @@ -311,7 +312,7 @@ def http_to_wsgi(http_dir): handler.auth_provider.checkRequest(handler, path) except websrv_lib.AuthRequiredExc, ae: # Darwin 9.x.x webdav clients will report "HTTP/1.0" to us, while they support (and need) the - # authorisation features of HTTP/1.1 + # authorisation features of HTTP/1.1 if request_version != 'HTTP/1.1' and ('Darwin/9.' not in handler.headers.get('User-Agent', '')): start_response("403 Forbidden", []) return [] @@ -373,6 +374,8 @@ def parse_http_response(s): # WSGI handlers registered through the register_wsgi_handler() function below. module_handlers = [] +# RPC endpoints registered through the register_rpc_endpoint() function below. +rpc_handlers = {} def register_wsgi_handler(handler): """ Register a WSGI handler. @@ -382,6 +385,11 @@ def register_wsgi_handler(handler): """ module_handlers.append(handler) +def register_rpc_endpoint(endpoint, handler): + """ Register a handler for a given RPC enpoint. + """ + rpc_handlers[endpoint] = handler + def application_unproxied(environ, start_response): """ WSGI entry point.""" openerp.service.start_internal() @@ -410,41 +418,63 @@ def application(environ, start_response): # The WSGI server, started by start_server(), stopped by stop_server(). httpd = None -def serve(): +def serve(interface, port, threaded): """ Serve HTTP requests via werkzeug development server. - If werkzeug can not be imported, we fall back to wsgiref's simple_server. - Calling this function is blocking, you might want to call it in its own thread. """ global httpd - - # TODO Change the xmlrpc_* options to http_* - interface = config['xmlrpc_interface'] or '0.0.0.0' - port = config['xmlrpc_port'] - if not openerp.tools.config.options["gevent"]: - httpd = werkzeug.serving.make_server(interface, port, application, threaded=True) + if not openerp.evented: + httpd = werkzeug.serving.make_server(interface, port, application, threaded=threaded) else: from gevent.wsgi import WSGIServer httpd = WSGIServer((interface, port), application) - _logger.info('HTTP service (werkzeug) running on %s:%s', interface, port) httpd.serve_forever() -def start_server(): +def start_service(): """ Call serve() in its own thread. The WSGI server can be shutdown with stop_server() below. """ - threading.Thread(target=serve).start() + # TODO Change the xmlrpc_* options to http_* + interface = config['xmlrpc_interface'] or '0.0.0.0' + port = config['xmlrpc_port'] + _logger.info('HTTP service (werkzeug) running on %s:%s', interface, port) + threading.Thread(target=serve, args=(interface, port, True)).start() -def stop_server(): +def stop_service(): """ Initiate the shutdown of the WSGI server. The server is supposed to have been started by start_server() above. """ if httpd: - httpd.shutdown() + if not openerp.evented: + httpd.shutdown() + close_socket(httpd.socket) + else: + import gevent + httpd.stop() + gevent.shutdown() + +def close_socket(sock): + """ Closes a socket instance cleanly + + :param sock: the network socket to close + :type sock: socket.socket + """ + try: + sock.shutdown(socket.SHUT_RDWR) + except socket.error, e: + # On OSX, socket shutdowns both sides if any side closes it + # causing an error 57 'Socket is not connected' on shutdown + # of the other side (or something), see + # http://bugs.python.org/issue4397 + # note: stdlib fixed test, not behavior + if e.errno != errno.ENOTCONN or platform.system() not in ['Darwin', 'Windows']: + raise + sock.close() + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: