[IMP] wsgi and http cleanups, static http is now handled in http.py
authorAntony Lesuisse <al@openerp.com>
Wed, 26 Mar 2014 13:20:57 +0000 (14:20 +0100)
committerAntony Lesuisse <al@openerp.com>
Wed, 26 Mar 2014 13:20:57 +0000 (14:20 +0100)
bzr revid: al@openerp.com-20140326132057-scuiqvqma9dhyorl

openerp/service/http_server.py [deleted file]
openerp/service/wsgi_server.py
openerp/tools/config.py

diff --git a/openerp/service/http_server.py b/openerp/service/http_server.py
deleted file mode 100644 (file)
index e25e75d..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright P. Christeas <p_christ@hol.gr> 2008-2010
-# Copyright 2010 OpenERP SA. (http://www.openerp.com)
-#
-#
-# WARNING: This program as such is intended to be used by professional
-# programmers who take the whole responsibility of assessing all potential
-# consequences resulting from its eventual inadequacies and bugs
-# End users who are looking for a ready-to-use solution with commercial
-# guarantees and support are strongly advised to contract a Free Software
-# Service Company
-#
-# This program is Free Software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-###############################################################################
-
-
-""" This module offers the family of HTTP-based servers. These are not a single
-    class/functionality, but a set of network stack layers, implementing
-    extendable HTTP protocols.
-
-    The OpenERP server defines a single instance of a HTTP server, listening at
-    the standard 8069, 8071 ports (well, it is 2 servers, and ports are 
-    configurable, of course). This "single" server then uses a `MultiHTTPHandler`
-    to dispatch requests to the appropriate channel protocol, like the XML-RPC,
-    static HTTP, DAV or other.
-"""
-
-import base64
-import posixpath
-import urllib
-import os
-import logging
-
-from websrv_lib import *
-import openerp.tools as tools
-
-try:
-    import fcntl
-except ImportError:
-    fcntl = None
-
-try:
-    from ssl import SSLError
-except ImportError:
-    class SSLError(Exception): pass
-
-_logger = logging.getLogger(__name__)
-
-# TODO delete this for 6.2, it is still needed for 6.1.
-class HttpLogHandler:
-    """ helper class for uniform log handling
-    Please define self._logger at each class that is derived from this
-    """
-    _logger = None
-    
-    def log_message(self, format, *args):
-        self._logger.debug(format % args) # todo: perhaps other level
-
-    def log_error(self, format, *args):
-        self._logger.error(format % args)
-        
-    def log_exception(self, format, *args):
-        self._logger.exception(format, *args)
-
-    def log_request(self, code='-', size='-'):
-        self._logger.debug('"%s" %s %s',
-            self.requestline, str(code), str(size))
-
-class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
-    _logger = logging.getLogger(__name__)
-
-    _HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD'] }
-
-    def __init__(self,request, client_address, server):
-        HTTPHandler.__init__(self,request,client_address,server)
-        document_root = tools.config.get('static_http_document_root', False)
-        assert document_root, "Please specify static_http_document_root in configuration, or disable static-httpd!"
-        self.__basepath = document_root
-
-    def translate_path(self, path):
-        """Translate a /-separated PATH to the local filename syntax.
-
-        Components that mean special things to the local file system
-        (e.g. drive or directory names) are ignored.  (XXX They should
-        probably be diagnosed.)
-
-        """
-        # abandon query parameters
-        path = path.split('?',1)[0]
-        path = path.split('#',1)[0]
-        path = posixpath.normpath(urllib.unquote(path))
-        words = path.split('/')
-        words = filter(None, words)
-        path = self.__basepath
-        for word in words:
-            if word in (os.curdir, os.pardir): continue
-            path = os.path.join(path, word)
-        return path
-
-def init_static_http():
-    if not tools.config.get('static_http_enable', False):
-        return
-    
-    document_root = tools.config.get('static_http_document_root', False)
-    assert document_root, "Document root must be specified explicitly to enable static HTTP service (option --static-http-document-root)"
-    
-    base_path = tools.config.get('static_http_url_prefix', '/')
-    
-    reg_http_service(base_path, StaticHTTPHandler)
-    
-    _logger.info("Registered HTTP dir %s for %s", document_root, base_path)
-
-import security
-
-class OpenERPAuthProvider(AuthProvider):
-    """ Require basic authentication."""
-    def __init__(self,realm='OpenERP User'):
-        self.realm = realm
-        self.auth_creds = {}
-        self.auth_tries = 0
-        self.last_auth = None
-
-    def authenticate(self, db, user, passwd, client_address):
-        try:
-            uid = security.login(db,user,passwd)
-            if uid is False:
-                return False
-            return user, passwd, db, uid
-        except Exception,e:
-            _logger.debug("Fail auth: %s" % e )
-            return False
-
-    def checkRequest(self,handler,path, db=False):        
-        auth_str = handler.headers.get('Authorization',False)
-        try:
-            if not db:
-                db = handler.get_db_from_path(path)
-        except Exception:
-            if path.startswith('/'):
-                path = path[1:]
-            psp= path.split('/')
-            if len(psp)>1:
-                db = psp[0]
-            else:
-                #FIXME!
-                _logger.info("Wrong path: %s, failing auth" %path)
-                raise AuthRejectedExc("Authorization failed. Wrong sub-path.") 
-        if self.auth_creds.get(db):
-            return True 
-        if auth_str and auth_str.startswith('Basic '):
-            auth_str=auth_str[len('Basic '):]
-            (user,passwd) = base64.decodestring(auth_str).split(':')
-            _logger.info("Found user=\"%s\", passwd=\"***\" for db=\"%s\"", user, db)
-            acd = self.authenticate(db,user,passwd,handler.client_address)
-            if acd != False:
-                self.auth_creds[db] = acd
-                self.last_auth = db
-                return True
-        if self.auth_tries > 5:
-            _logger.info("Failing authorization after 5 requests w/o password")
-            raise AuthRejectedExc("Authorization failed.")
-        self.auth_tries += 1
-        raise AuthRequiredExc(atype='Basic', realm=self.realm)
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index b31736b..5e72ba5 100644 (file)
@@ -164,153 +164,6 @@ def wsgi_xmlrpc(environ, start_response):
         params, method = xmlrpclib.loads(data)
         return xmlrpc_return(start_response, service, method, params, string_faultcode)
 
-def wsgi_webdav(environ, start_response):
-    pi = environ['PATH_INFO']
-    if environ['REQUEST_METHOD'] == 'OPTIONS' and pi in ['*','/']:
-        return return_options(environ, start_response)
-    elif pi.startswith('/webdav'):
-        http_dir = websrv_lib.find_http_service(pi)
-        if http_dir:
-            path = pi[len(http_dir.path):]
-            if path.startswith('/'):
-                environ['PATH_INFO'] = path
-            else:
-                environ['PATH_INFO'] = '/' + path
-            return http_to_wsgi(http_dir)(environ, start_response)
-
-def return_options(environ, start_response):
-    # Microsoft specific header, see
-    # http://www.ibm.com/developerworks/rational/library/2089.html
-    if 'Microsoft' in environ.get('User-Agent', ''):
-        options = [('MS-Author-Via', 'DAV')]
-    else:
-        options = []
-    options += [('DAV', '1 2'), ('Allow', 'GET HEAD PROPFIND OPTIONS REPORT')]
-    start_response("200 OK", [('Content-Length', str(0))] + options)
-    return []
-
-def http_to_wsgi(http_dir):
-    """
-    Turn a BaseHTTPRequestHandler into a WSGI entry point.
-
-    Actually the argument is not a bare BaseHTTPRequestHandler but is wrapped
-    (as a class, so it needs to be instanciated) in a HTTPDir.
-
-    This code is adapted from wbsrv_lib.MultiHTTPHandler._handle_one_foreign().
-    It is a temporary solution: the HTTP sub-handlers (in particular the
-    document_webdav addon) have to be WSGIfied.
-    """
-    def wsgi_handler(environ, start_response):
-
-        headers = {}
-        for key, value in environ.items():
-            if key.startswith('HTTP_'):
-                key = key[5:].replace('_', '-').title()
-                headers[key] = value
-            if key == 'CONTENT_LENGTH':
-                key = key.replace('_', '-').title()
-                headers[key] = value
-        if environ.get('Content-Type'):
-            headers['Content-Type'] = environ['Content-Type']
-
-        path = urllib.quote(environ.get('PATH_INFO', ''))
-        if environ.get('QUERY_STRING'):
-            path += '?' + environ['QUERY_STRING']
-
-        request_version = 'HTTP/1.1' # TODO
-        request_line = "%s %s %s\n" % (environ['REQUEST_METHOD'], path, request_version)
-
-        class Dummy(object):
-            pass
-
-        # Let's pretend we have a server to hand to the handler.
-        server = Dummy()
-        server.server_name = environ['SERVER_NAME']
-        server.server_port = int(environ['SERVER_PORT'])
-
-        # Initialize the underlying handler and associated auth. provider.
-        con = openerp.service.websrv_lib.noconnection(environ['wsgi.input'])
-        handler = http_dir.instanciate_handler(con, environ['REMOTE_ADDR'], server)
-
-        # Populate the handler as if it is called by a regular HTTP server
-        # and the request is already parsed.
-        handler.wfile = StringIO.StringIO()
-        handler.rfile = environ['wsgi.input']
-        handler.headers = headers
-        handler.command = environ['REQUEST_METHOD']
-        handler.path = path
-        handler.request_version = request_version
-        handler.close_connection = 1
-        handler.raw_requestline = request_line
-        handler.requestline = request_line
-
-        # Handle authentication if there is an auth. provider associated to
-        # the handler.
-        if hasattr(handler, 'auth_provider'):
-            try:
-                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
-                if request_version != 'HTTP/1.1' and ('Darwin/9.' not in handler.headers.get('User-Agent', '')):
-                    start_response("403 Forbidden", [])
-                    return []
-                start_response("401 Authorization required", [
-                    ('WWW-Authenticate', '%s realm="%s"' % (ae.atype,ae.realm)),
-                    # ('Connection', 'keep-alive'),
-                    ('Content-Type', 'text/html'),
-                    ('Content-Length', 4), # len(self.auth_required_msg)
-                    ])
-                return ['Blah'] # self.auth_required_msg
-            except websrv_lib.AuthRejectedExc,e:
-                start_response("403 %s" % (e.args[0],), [])
-                return []
-
-        method_name = 'do_' + handler.command
-
-        # Support the OPTIONS method even when not provided directly by the
-        # handler. TODO I would prefer to remove it and fix the handler if
-        # needed.
-        if not hasattr(handler, method_name):
-            if handler.command == 'OPTIONS':
-                return return_options(environ, start_response)
-            start_response("501 Unsupported method (%r)" % handler.command, [])
-            return []
-
-        # Finally, call the handler's method.
-        try:
-            method = getattr(handler, method_name)
-            method()
-            # The DAV handler buffers its output and provides a _flush()
-            # method.
-            getattr(handler, '_flush', lambda: None)()
-            response = parse_http_response(handler.wfile.getvalue())
-            response_headers = response.getheaders()
-            body = response.read()
-            start_response(str(response.status) + ' ' + response.reason, response_headers)
-            return [body]
-        except (websrv_lib.AuthRejectedExc, websrv_lib.AuthRequiredExc):
-            raise
-        except Exception, e:
-            start_response("500 Internal error", [])
-            return []
-
-    return wsgi_handler
-
-def parse_http_response(s):
-    """ Turn a HTTP response string into a httplib.HTTPResponse object."""
-    class DummySocket(StringIO.StringIO):
-        """
-        This is used to provide a StringIO to httplib.HTTPResponse
-        which, instead of taking a file object, expects a socket and
-        uses its makefile() method.
-        """
-        def makefile(self, *args, **kw):
-            return self
-    response = httplib.HTTPResponse(DummySocket(s))
-    response.begin()
-    return response
-
 # WSGI handlers registered through the register_wsgi_handler() function below.
 module_handlers = []
 # RPC endpoints registered through the register_rpc_endpoint() function below.
@@ -342,7 +195,7 @@ def application_unproxied(environ, start_response):
         del threading.current_thread().dbname
 
     # Try all handlers until one returns some result (i.e. not None).
-    wsgi_handlers = [wsgi_xmlrpc, wsgi_webdav]
+    wsgi_handlers = [wsgi_xmlrpc]
     wsgi_handlers += module_handlers
     for handler in wsgi_handlers:
         result = handler(environ, start_response)
index f20cd65..6b21bda 100644 (file)
@@ -152,19 +152,11 @@ class configmanager(object):
         parser.add_option_group(group)
 
         # WEB
-        # TODO move to web addons after MetaOption merge
         group = optparse.OptionGroup(parser, "Web interface Configuration")
         group.add_option("--db-filter", dest="dbfilter", default='.*',
                          help="Filter listed database", metavar="REGEXP")
         parser.add_option_group(group)
 
-        # Static HTTP
-        group = optparse.OptionGroup(parser, "Static HTTP service")
-        group.add_option("--static-http-enable", dest="static_http_enable", action="store_true", my_default=False, help="enable static HTTP service for serving plain HTML files")
-        group.add_option("--static-http-document-root", dest="static_http_document_root", help="specify the directory containing your static HTML files (e.g '/var/www/')")
-        group.add_option("--static-http-url-prefix", dest="static_http_url_prefix", help="specify the URL root prefix where you want web browsers to access your static HTML files (e.g '/')")
-        parser.add_option_group(group)
-
         # Testing Group
         group = optparse.OptionGroup(parser, "Testing Configuration")
         group.add_option("--test-file", dest="test_file", my_default=False,
@@ -394,7 +386,6 @@ class configmanager(object):
                 'db_maxconn', 'import_partial', 'addons_path',
                 'xmlrpc', 'syslog', 'without_demo', 'timezone',
                 'xmlrpcs_interface', 'xmlrpcs_port', 'xmlrpcs',
-                'static_http_enable', 'static_http_document_root', 'static_http_url_prefix',
                 'secure_cert_file', 'secure_pkey_file', 'dbfilter', 'log_handler', 'log_level', 'log_db'
                 ]