mercurial/hgweb/server.py
changeset 18354 cf5c76017e11
parent 18353 a9fd11ffa13f
child 18380 a4d7fd7ad1f7
equal deleted inserted replaced
18353:a9fd11ffa13f 18354:cf5c76017e11
   131 
   131 
   132         self.saved_status = None
   132         self.saved_status = None
   133         self.saved_headers = []
   133         self.saved_headers = []
   134         self.sent_headers = False
   134         self.sent_headers = False
   135         self.length = None
   135         self.length = None
       
   136         self._chunked = None
   136         for chunk in self.server.application(env, self._start_response):
   137         for chunk in self.server.application(env, self._start_response):
   137             self._write(chunk)
   138             self._write(chunk)
   138         if not self.sent_headers:
   139         if not self.sent_headers:
   139             self.send_headers()
   140             self.send_headers()
       
   141         self._done()
   140 
   142 
   141     def send_headers(self):
   143     def send_headers(self):
   142         if not self.saved_status:
   144         if not self.saved_status:
   143             raise AssertionError("Sending headers before "
   145             raise AssertionError("Sending headers before "
   144                                  "start_response() called")
   146                                  "start_response() called")
   145         saved_status = self.saved_status.split(None, 1)
   147         saved_status = self.saved_status.split(None, 1)
   146         saved_status[0] = int(saved_status[0])
   148         saved_status[0] = int(saved_status[0])
   147         self.send_response(*saved_status)
   149         self.send_response(*saved_status)
   148         should_close = True
   150         self.length = None
       
   151         self._chunked = False
   149         for h in self.saved_headers:
   152         for h in self.saved_headers:
   150             self.send_header(*h)
   153             self.send_header(*h)
   151             if h[0].lower() == 'content-length':
   154             if h[0].lower() == 'content-length':
   152                 should_close = False
       
   153                 self.length = int(h[1])
   155                 self.length = int(h[1])
   154         # The value of the Connection header is a list of case-insensitive
   156         if self.length is None:
   155         # tokens separated by commas and optional whitespace.
   157             self._chunked = (not self.close_connection and
   156         if should_close:
   158                              self.request_version == "HTTP/1.1")
   157             self.send_header('Connection', 'close')
   159             if self._chunked:
       
   160                 self.send_header('Transfer-Encoding', 'chunked')
       
   161             else:
       
   162                 self.send_header('Connection', 'close')
   158         self.end_headers()
   163         self.end_headers()
   159         self.sent_headers = True
   164         self.sent_headers = True
   160 
   165 
   161     def _start_response(self, http_status, headers, exc_info=None):
   166     def _start_response(self, http_status, headers, exc_info=None):
   162         code, msg = http_status.split(None, 1)
   167         code, msg = http_status.split(None, 1)
   175         if self.length is not None:
   180         if self.length is not None:
   176             if len(data) > self.length:
   181             if len(data) > self.length:
   177                 raise AssertionError("Content-length header sent, but more "
   182                 raise AssertionError("Content-length header sent, but more "
   178                                      "bytes than specified are being written.")
   183                                      "bytes than specified are being written.")
   179             self.length = self.length - len(data)
   184             self.length = self.length - len(data)
       
   185         elif self._chunked and data:
       
   186             data = '%x\r\n%s\r\n' % (len(data), data)
   180         self.wfile.write(data)
   187         self.wfile.write(data)
   181         self.wfile.flush()
   188         self.wfile.flush()
       
   189 
       
   190     def _done(self):
       
   191         if self._chunked:
       
   192             self.wfile.write('0\r\n\r\n')
       
   193             self.wfile.flush()
   182 
   194 
   183 class _httprequesthandleropenssl(_httprequesthandler):
   195 class _httprequesthandleropenssl(_httprequesthandler):
   184     """HTTPS handler based on pyOpenSSL"""
   196     """HTTPS handler based on pyOpenSSL"""
   185 
   197 
   186     url_scheme = 'https'
   198     url_scheme = 'https'