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]) |