##// END OF EJS Templates
Add SSL support to hg serve, activated via --certificate option
Brendan Cully -
r4860:f3802f9f default
parent child Browse files
Show More
@@ -2464,7 +2464,7 b' def serve(ui, repo, **opts):'
2464
2464
2465 parentui = ui.parentui or ui
2465 parentui = ui.parentui or ui
2466 optlist = ("name templates style address port ipv6"
2466 optlist = ("name templates style address port ipv6"
2467 " accesslog errorlog webdir_conf")
2467 " accesslog errorlog webdir_conf certificate")
2468 for o in optlist.split():
2468 for o in optlist.split():
2469 if opts[o]:
2469 if opts[o]:
2470 parentui.setconfig("web", o, str(opts[o]))
2470 parentui.setconfig("web", o, str(opts[o]))
@@ -3072,7 +3072,8 b' table = {'
3072 ('', 'stdio', None, _('for remote clients')),
3072 ('', 'stdio', None, _('for remote clients')),
3073 ('t', 'templates', '', _('web templates to use')),
3073 ('t', 'templates', '', _('web templates to use')),
3074 ('', 'style', '', _('template style to use')),
3074 ('', 'style', '', _('template style to use')),
3075 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
3075 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3076 ('', 'certificate', '', _('SSL certificate file'))],
3076 _('hg serve [OPTION]...')),
3077 _('hg serve [OPTION]...')),
3077 "^status|st":
3078 "^status|st":
3078 (status,
3079 (status,
@@ -53,13 +53,16 b' class _hgwebhandler(object, BaseHTTPServ'
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")
@@ -164,6 +167,28 b' class _hgwebhandler(object, BaseHTTPServ'
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
@@ -176,6 +201,7 b' def create_server(ui, repo):'
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
@@ -222,6 +248,19 b' def create_server(ui, repo):'
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
@@ -230,10 +269,15 b' def create_server(ui, repo):'
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])
General Comments 0
You need to be logged in to leave comments. Login now