mercurial/hgweb/server.py
changeset 2506 d0db3462d568
parent 2505 01b856927970
child 2507 7e01da2bc7f3
equal deleted inserted replaced
2505:01b856927970 2506:d0db3462d568
     8 
     8 
     9 from mercurial.demandload import demandload
     9 from mercurial.demandload import demandload
    10 import os, sys, errno
    10 import os, sys, errno
    11 demandload(globals(), "urllib BaseHTTPServer socket SocketServer")
    11 demandload(globals(), "urllib BaseHTTPServer socket SocketServer")
    12 demandload(globals(), "mercurial:ui,hg,util,templater")
    12 demandload(globals(), "mercurial:ui,hg,util,templater")
    13 demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:hgrequest")
    13 demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:wsgiapplication")
    14 from mercurial.i18n import gettext as _
    14 from mercurial.i18n import gettext as _
    15 
    15 
    16 def _splitURI(uri):
    16 def _splitURI(uri):
    17     """ Return path and query splited from uri
    17     """ Return path and query splited from uri
    18 
    18 
    22     if '?' in uri:
    22     if '?' in uri:
    23         path, query = uri.split('?', 1)
    23         path, query = uri.split('?', 1)
    24     else:
    24     else:
    25         path, query = uri, ''
    25         path, query = uri, ''
    26     return urllib.unquote(path), query
    26     return urllib.unquote(path), query
       
    27 
       
    28 class _error_logger(object):
       
    29     def __init__(self, handler):
       
    30         self.handler = handler
       
    31     def flush(self):
       
    32         pass
       
    33     def write(str):
       
    34         self.writelines(str.split('\n'))
       
    35     def writelines(seq):
       
    36         for msg in seq:
       
    37             self.handler.log_error("HG error:  %s", msg)
    27 
    38 
    28 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
    39 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
    29     def __init__(self, *args, **kargs):
    40     def __init__(self, *args, **kargs):
    30         self.protocol_version = 'HTTP/1.1'
    41         self.protocol_version = 'HTTP/1.1'
    31         BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
    42         BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
    82             hval = self.headers.getheader(header)
    93             hval = self.headers.getheader(header)
    83             hval = hval.replace('\n', '').strip()
    94             hval = hval.replace('\n', '').strip()
    84             if hval:
    95             if hval:
    85                 env[hkey] = hval
    96                 env[hkey] = hval
    86         env['SERVER_PROTOCOL'] = self.request_version
    97         env['SERVER_PROTOCOL'] = self.request_version
    87 
    98         env['wsgi.version'] = (1, 0)
    88         req = hgrequest(self.rfile, self.wfile, env)
    99         env['wsgi.url_scheme'] = 'http'
    89         self.send_response(200, "Script output follows")
   100         env['wsgi.input'] = self.rfile
    90         self.close_connection = self.server.make_and_run_handler(req)
   101         env['wsgi.errors'] = _error_logger(self)
       
   102         env['wsgi.multithread'] = isinstance(self.server,
       
   103                                              SocketServer.ThreadingMixIn)
       
   104         env['wsgi.multiprocess'] = isinstance(self.server,
       
   105                                               SocketServer.ForkingMixIn)
       
   106         env['wsgi.run_once'] = 0
       
   107 
       
   108         self.close_connection = True
       
   109         self.saved_status = None
       
   110         self.saved_headers = []
       
   111         self.sent_headers = False
       
   112         req = self.server.reqmaker(env, self._start_response)
       
   113         for data in req:
       
   114             if data:
       
   115                 self._write(data)
       
   116 
       
   117     def send_headers(self):
       
   118         if not self.saved_status:
       
   119             raise AssertionError("Sending headers before start_response() called")
       
   120         saved_status = self.saved_status.split(None, 1)
       
   121         saved_status[0] = int(saved_status[0])
       
   122         self.send_response(*saved_status)
       
   123         for h in self.saved_headers:
       
   124             self.send_header(*h)
       
   125         self.end_headers()
       
   126         self.sent_headers = True
       
   127 
       
   128     def _start_response(self, http_status, headers, exc_info=None):
       
   129         code, msg = http_status.split(None, 1)
       
   130         code = int(code)
       
   131         self.saved_status = http_status
       
   132         self.saved_headers = headers
       
   133         return self._write
       
   134 
       
   135     def _write(self, data):
       
   136         if not self.saved_status:
       
   137             raise AssertionError("data written before start_response() called")
       
   138         elif not self.sent_headers:
       
   139             self.send_headers()
       
   140         self.wfile.write(data)
       
   141         self.wfile.flush()
    91 
   142 
    92 def create_server(ui, repo):
   143 def create_server(ui, repo):
    93     use_threads = True
   144     use_threads = True
    94 
   145 
    95     def openlog(opt, default):
   146     def openlog(opt, default):
   125             self.errorlog = errorlog
   176             self.errorlog = errorlog
   126             self.repo = repo
   177             self.repo = repo
   127             self.webdir_conf = webdir_conf
   178             self.webdir_conf = webdir_conf
   128             self.webdirmaker = hgwebdir
   179             self.webdirmaker = hgwebdir
   129             self.repoviewmaker = hgweb
   180             self.repoviewmaker = hgweb
   130 
   181             self.reqmaker = wsgiapplication(self.make_handler)
   131         def make_and_run_handler(self, req):
   182 
       
   183         def make_handler(self):
   132             if self.webdir_conf:
   184             if self.webdir_conf:
   133                 hgwebobj = self.webdirmaker(self.webdir_conf)
   185                 hgwebobj = self.webdirmaker(self.webdir_conf)
   134             elif self.repo is not None:
   186             elif self.repo is not None:
   135                 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui,
   187                 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui,
   136                                                              repo.origroot))
   188                                                              repo.origroot))
   137             else:
   189             else:
   138                 raise hg.RepoError(_('no repo found'))
   190                 raise hg.RepoError(_('no repo found'))
   139             hgwebobj.run(req)
   191             return hgwebobj
   140             return req.will_close
       
   141 
   192 
   142     class IPv6HTTPServer(MercurialHTTPServer):
   193     class IPv6HTTPServer(MercurialHTTPServer):
   143         address_family = getattr(socket, 'AF_INET6', None)
   194         address_family = getattr(socket, 'AF_INET6', None)
   144 
   195 
   145         def __init__(self, *args, **kwargs):
   196         def __init__(self, *args, **kwargs):