mercurial/hgweb/server.py
changeset 4850 f3802f9f1840
parent 4635 63b9d2deed48
child 4868 192cd95c2ba8
equal deleted inserted replaced
4849:8c5aca855b5d 4850:f3802f9f1840
    51         accesslog = self.server.accesslog
    51         accesslog = self.server.accesslog
    52         accesslog.write("%s - - [%s] %s\n" % (self.client_address[0],
    52         accesslog.write("%s - - [%s] %s\n" % (self.client_address[0],
    53                                               self.log_date_time_string(),
    53                                               self.log_date_time_string(),
    54                                               format % args))
    54                                               format % args))
    55 
    55 
       
    56     def do_write(self):
       
    57         try:
       
    58             self.do_hgweb()
       
    59         except socket.error, inst:
       
    60             if inst[0] != errno.EPIPE:
       
    61                 raise
       
    62 
    56     def do_POST(self):
    63     def do_POST(self):
    57         try:
    64         try:
    58             try:
    65             self.do_write()
    59                 self.do_hgweb()
       
    60             except socket.error, inst:
       
    61                 if inst[0] != errno.EPIPE:
       
    62                     raise
       
    63         except StandardError, inst:
    66         except StandardError, inst:
    64             self._start_response("500 Internal Server Error", [])
    67             self._start_response("500 Internal Server Error", [])
    65             self._write("Internal Server Error")
    68             self._write("Internal Server Error")
    66             tb = "".join(traceback.format_exception(*sys.exc_info()))
    69             tb = "".join(traceback.format_exception(*sys.exc_info()))
    67             self.log_error("Exception happened during processing request '%s':\n%s",
    70             self.log_error("Exception happened during processing request '%s':\n%s",
   162                 raise AssertionError("Content-length header sent, but more bytes than specified are being written.")
   165                 raise AssertionError("Content-length header sent, but more bytes than specified are being written.")
   163             self.length = self.length - len(data)
   166             self.length = self.length - len(data)
   164         self.wfile.write(data)
   167         self.wfile.write(data)
   165         self.wfile.flush()
   168         self.wfile.flush()
   166 
   169 
       
   170 class _shgwebhandler(_hgwebhandler):
       
   171     def setup(self):
       
   172         self.connection = self.request
       
   173         self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
       
   174         self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
       
   175 
       
   176     def do_write(self):
       
   177         from OpenSSL.SSL import SysCallError
       
   178         try:
       
   179             super(_shgwebhandler, self).do_write()
       
   180         except SysCallError, inst:
       
   181             if inst.args[0] != errno.EPIPE:
       
   182                 raise
       
   183 
       
   184     def handle_one_request(self):
       
   185         from OpenSSL.SSL import SysCallError, ZeroReturnError
       
   186         try:
       
   187             super(_shgwebhandler, self).handle_one_request()
       
   188         except (SysCallError, ZeroReturnError):
       
   189             self.close_connection = True
       
   190             pass
       
   191 
   167 def create_server(ui, repo):
   192 def create_server(ui, repo):
   168     use_threads = True
   193     use_threads = True
   169 
   194 
   170     def openlog(opt, default):
   195     def openlog(opt, default):
   171         if opt and opt != '-':
   196         if opt and opt != '-':
   174 
   199 
   175     address = ui.config("web", "address", "")
   200     address = ui.config("web", "address", "")
   176     port = int(ui.config("web", "port", 8000))
   201     port = int(ui.config("web", "port", 8000))
   177     use_ipv6 = ui.configbool("web", "ipv6")
   202     use_ipv6 = ui.configbool("web", "ipv6")
   178     webdir_conf = ui.config("web", "webdir_conf")
   203     webdir_conf = ui.config("web", "webdir_conf")
       
   204     ssl_cert = ui.config("web", "certificate")
   179     accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout)
   205     accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout)
   180     errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr)
   206     errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr)
   181 
   207 
   182     if use_threads:
   208     if use_threads:
   183         try:
   209         try:
   220             if addr in ('', '::'):
   246             if addr in ('', '::'):
   221                 addr = socket.gethostname()
   247                 addr = socket.gethostname()
   222 
   248 
   223             self.addr, self.port = addr, port
   249             self.addr, self.port = addr, port
   224 
   250 
       
   251             if ssl_cert:
       
   252                 try:
       
   253                     from OpenSSL import SSL
       
   254                     ctx = SSL.Context(SSL.SSLv23_METHOD)
       
   255                 except ImportError:
       
   256                     raise util.Abort("SSL support is unavailable")
       
   257                 ctx.use_privatekey_file(ssl_cert)
       
   258                 ctx.use_certificate_file(ssl_cert)
       
   259                 sock = socket.socket(self.address_family, self.socket_type)
       
   260                 self.socket = SSL.Connection(ctx, sock)
       
   261                 self.server_bind()
       
   262                 self.server_activate()
       
   263 
   225     class IPv6HTTPServer(MercurialHTTPServer):
   264     class IPv6HTTPServer(MercurialHTTPServer):
   226         address_family = getattr(socket, 'AF_INET6', None)
   265         address_family = getattr(socket, 'AF_INET6', None)
   227 
   266 
   228         def __init__(self, *args, **kwargs):
   267         def __init__(self, *args, **kwargs):
   229             if self.address_family is None:
   268             if self.address_family is None:
   230                 raise hg.RepoError(_('IPv6 not available on this system'))
   269                 raise hg.RepoError(_('IPv6 not available on this system'))
   231             super(IPv6HTTPServer, self).__init__(*args, **kwargs)
   270             super(IPv6HTTPServer, self).__init__(*args, **kwargs)
   232 
   271 
       
   272     if ssl_cert:
       
   273         handler = _shgwebhandler
       
   274     else:
       
   275         handler = _hgwebhandler
       
   276 
   233     try:
   277     try:
   234         if use_ipv6:
   278         if use_ipv6:
   235             return IPv6HTTPServer((address, port), _hgwebhandler)
   279             return IPv6HTTPServer((address, port), handler)
   236         else:
   280         else:
   237             return MercurialHTTPServer((address, port), _hgwebhandler)
   281             return MercurialHTTPServer((address, port), handler)
   238     except socket.error, inst:
   282     except socket.error, inst:
   239         raise util.Abort(_('cannot start server: %s') % inst.args[1])
   283         raise util.Abort(_('cannot start server: %s') % inst.args[1])