~camptocamp/openobject-server/trunk-geoengine

« back to all changes in this revision

Viewing changes to openerp/service/http_server.py

  • Committer: nicolas.bessi at camptocamp
  • Date: 2011-09-29 08:01:19 UTC
  • mfrom: (3575.1.98 trunk)
  • Revision ID: nicolas.bessi@camptocamp.com-20110929080119-dd1mtrue3ooxvhqh
[MRG] from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
except ImportError:
65
65
    class SSLError(Exception): pass
66
66
 
67
 
class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer):
68
 
    """ A threaded httpd server, with all the necessary functionality for us.
69
 
 
70
 
        It also inherits the xml-rpc dispatcher, so that some xml-rpc functions
71
 
        will be available to the request handler
72
 
    """
73
 
    encoding = None
74
 
    allow_none = False
75
 
    allow_reuse_address = 1
76
 
    _send_traceback_header = False
77
 
    i = 0
78
 
 
79
 
    def __init__(self, addr, requestHandler, proto='http',
80
 
                 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
81
 
        self.logRequests = logRequests
82
 
 
83
 
        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
84
 
        HTTPServer.__init__(self, addr, requestHandler)
85
 
        
86
 
        self.numThreads = 0
87
 
        self.proto = proto
88
 
        self.__threadno = 0
89
 
 
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)
97
 
 
98
 
    def handle_error(self, request, client_address):
99
 
        """ Override the error handler
100
 
        """
101
 
        
102
 
        logging.getLogger("init").exception("Server error in request from %s:" % (client_address,))
103
 
 
104
 
    def _mark_start(self, thread):
105
 
        self.numThreads += 1
106
 
 
107
 
    def _mark_end(self, thread):
108
 
        self.numThreads -= 1
109
 
 
110
 
 
111
 
    def _get_next_name(self):
112
 
        self.__threadno += 1
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))
132
 
    
133
 
class MultiHandler2(HttpLogHandler, MultiHTTPHandler):
134
 
    _logger = logging.getLogger('http')
135
 
 
136
 
 
137
 
class SecureMultiHandler2(HttpLogHandler, SecureMultiHTTPHandler):
138
 
    _logger = logging.getLogger('https')
139
 
 
140
 
    def getcert_fnames(self):
141
 
        tc = tools.config
142
 
        fcert = tc.get('secure_cert_file', 'server.cert')
143
 
        fkey = tc.get('secure_pkey_file', 'server.key')
144
 
        return (fcert,fkey)
145
 
 
146
 
class BaseHttpDaemon(threading.Thread, netsvc.Server):
147
 
    _RealProto = '??'
148
 
 
149
 
    def __init__(self, interface, port, handler):
150
 
        threading.Thread.__init__(self, name='%sDaemon-%d'%(self._RealProto, port))
151
 
        netsvc.Server.__init__(self)
152
 
        self.__port = port
153
 
        self.__interface = interface
154
 
 
155
 
        try:
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,))
162
 
        except Exception, e:
163
 
            logging.getLogger("httpd").exception("Error occured when starting the server daemon.")
164
 
            raise
165
 
 
166
 
    @property
167
 
    def socket(self):
168
 
        return self.server.socket
169
 
 
170
 
    def attach(self, path, gw):
171
 
        pass
172
 
 
173
 
    def stop(self):
174
 
        self.running = False
175
 
        self._close_socket()
176
 
 
177
 
    def run(self):
178
 
        self.running = True
179
 
        while self.running:
180
 
            try:
181
 
                self.server.handle_request()
182
 
            except (socket.error, select.error), e:
183
 
                if self.running or e.args[0] != errno.EBADF:
184
 
                    raise
185
 
        return True
186
 
 
187
 
    def stats(self):
188
 
        res = "%sd: " % self._RealProto + ((self.running and "running") or  "stopped")
189
 
        if self.server:
190
 
            res += ", %d threads" % (self.server.numThreads,)
191
 
        return res
192
 
 
193
 
# No need for these two classes: init_server() below can initialize correctly
194
 
# directly the BaseHttpDaemon class.
195
 
class HttpDaemon(BaseHttpDaemon):
196
 
    _RealProto = 'HTTP'
197
 
    def __init__(self, interface, port):
198
 
        super(HttpDaemon, self).__init__(interface, port,
199
 
                                         handler=MultiHandler2)
200
 
 
201
 
class HttpSDaemon(BaseHttpDaemon):
202
 
    _RealProto = 'HTTPS'
203
 
    def __init__(self, interface, port):
204
 
        try:
205
 
            super(HttpSDaemon, self).__init__(interface, port,
206
 
                                              handler=SecureMultiHandler2)
207
 
        except SSLError, e:
208
 
            logging.getLogger('httpsd').exception( \
209
 
                        "Can not load the certificate and/or the private key files")
210
 
            raise
211
 
 
212
 
httpd = None
213
 
httpsd = None
214
 
 
215
 
def init_servers():
216
 
    global httpd, httpsd
217
 
    if tools.config.get('xmlrpc'):
218
 
        httpd = HttpDaemon(tools.config.get('xmlrpc_interface', ''),
219
 
                           int(tools.config.get('xmlrpc_port', 8069)))
220
 
 
221
 
    if tools.config.get('xmlrpcs'):
222
 
        httpsd = HttpSDaemon(tools.config.get('xmlrpcs_interface', ''),
223
 
                             int(tools.config.get('xmlrpcs_port', 8071)))
224
 
 
225
 
import SimpleXMLRPCServer
226
 
class XMLRPCRequestHandler(FixSendError,HttpLogHandler,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
227
 
    rpc_paths = []
228
 
    protocol_version = 'HTTP/1.1'
229
 
    _logger = logging.getLogger('xmlrpc')
230
 
 
231
 
    def _dispatch(self, method, params):
232
 
        try:
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)
238
 
 
239
 
    def handle(self):
240
 
        pass
241
 
 
242
 
    def finish(self):
243
 
        pass
244
 
 
245
 
    def setup(self):
246
 
        self.connection = dummyconn()
247
 
        self.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys())
248
 
 
249
 
 
250
 
def init_xmlrpc():
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")
256
 
 
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")
262
85
 
263
86
class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
264
87
    _logger = logging.getLogger('httpd')