64
64
except ImportError:
65
65
class SSLError(Exception): pass
67
class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer):
68
""" A threaded httpd server, with all the necessary functionality for us.
70
It also inherits the xml-rpc dispatcher, so that some xml-rpc functions
71
will be available to the request handler
75
allow_reuse_address = 1
76
_send_traceback_header = False
79
def __init__(self, addr, requestHandler, proto='http',
80
logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
81
self.logRequests = logRequests
83
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
84
HTTPServer.__init__(self, addr, requestHandler)
90
# [Bug #1222790] If possible, set close-on-exec flag; if a
91
# method spawns a subprocess, the subprocess shouldn't have
92
# the listening socket open.
93
if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
94
flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
95
flags |= fcntl.FD_CLOEXEC
96
fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
98
def handle_error(self, request, client_address):
99
""" Override the error handler
102
logging.getLogger("init").exception("Server error in request from %s:" % (client_address,))
104
def _mark_start(self, thread):
107
def _mark_end(self, thread):
111
def _get_next_name(self):
113
return 'http-client-%d' % self.__threadno
114
67
class HttpLogHandler:
115
68
""" helper class for uniform log handling
116
69
Please define self._logger at each class that is derived from this
129
82
def log_request(self, code='-', size='-'):
130
83
self._logger.log(netsvc.logging.DEBUG_RPC, '"%s" %s %s',
131
84
self.requestline, str(code), str(size))
133
class MultiHandler2(HttpLogHandler, MultiHTTPHandler):
134
_logger = logging.getLogger('http')
137
class SecureMultiHandler2(HttpLogHandler, SecureMultiHTTPHandler):
138
_logger = logging.getLogger('https')
140
def getcert_fnames(self):
142
fcert = tc.get('secure_cert_file', 'server.cert')
143
fkey = tc.get('secure_pkey_file', 'server.key')
146
class BaseHttpDaemon(threading.Thread, netsvc.Server):
149
def __init__(self, interface, port, handler):
150
threading.Thread.__init__(self, name='%sDaemon-%d'%(self._RealProto, port))
151
netsvc.Server.__init__(self)
153
self.__interface = interface
156
self.server = ThreadedHTTPServer((interface, port), handler, proto=self._RealProto)
157
self.server.logRequests = True
158
self.server.timeout = self._busywait_timeout
159
logging.getLogger("web-services").info(
160
"starting %s service at %s port %d" %
161
(self._RealProto, interface or '0.0.0.0', port,))
163
logging.getLogger("httpd").exception("Error occured when starting the server daemon.")
168
return self.server.socket
170
def attach(self, path, gw):
181
self.server.handle_request()
182
except (socket.error, select.error), e:
183
if self.running or e.args[0] != errno.EBADF:
188
res = "%sd: " % self._RealProto + ((self.running and "running") or "stopped")
190
res += ", %d threads" % (self.server.numThreads,)
193
# No need for these two classes: init_server() below can initialize correctly
194
# directly the BaseHttpDaemon class.
195
class HttpDaemon(BaseHttpDaemon):
197
def __init__(self, interface, port):
198
super(HttpDaemon, self).__init__(interface, port,
199
handler=MultiHandler2)
201
class HttpSDaemon(BaseHttpDaemon):
203
def __init__(self, interface, port):
205
super(HttpSDaemon, self).__init__(interface, port,
206
handler=SecureMultiHandler2)
208
logging.getLogger('httpsd').exception( \
209
"Can not load the certificate and/or the private key files")
217
if tools.config.get('xmlrpc'):
218
httpd = HttpDaemon(tools.config.get('xmlrpc_interface', ''),
219
int(tools.config.get('xmlrpc_port', 8069)))
221
if tools.config.get('xmlrpcs'):
222
httpsd = HttpSDaemon(tools.config.get('xmlrpcs_interface', ''),
223
int(tools.config.get('xmlrpcs_port', 8071)))
225
import SimpleXMLRPCServer
226
class XMLRPCRequestHandler(FixSendError,HttpLogHandler,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
228
protocol_version = 'HTTP/1.1'
229
_logger = logging.getLogger('xmlrpc')
231
def _dispatch(self, method, params):
233
service_name = self.path.split("/")[-1]
234
auth = getattr(self, 'auth_provider', None)
235
return netsvc.dispatch_rpc(service_name, method, params, auth)
236
except netsvc.OpenERPDispatcherException, e:
237
raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback)
246
self.connection = dummyconn()
247
self.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys())
251
if tools.config.get('xmlrpc', False):
252
# Example of http file serving:
253
# reg_http_service('/test/', HTTPHandler)
254
reg_http_service('/xmlrpc/', XMLRPCRequestHandler)
255
logging.getLogger("web-services").info("Registered XML-RPC over HTTP")
257
if tools.config.get('xmlrpcs', False) \
258
and not tools.config.get('xmlrpc', False):
259
# only register at the secure server
260
reg_http_service('/xmlrpc/', XMLRPCRequestHandler, secure_only=True)
261
logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only")
263
86
class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
264
87
_logger = logging.getLogger('httpd')