changeset 12740:b86c6954ec4c

serve: fix https mode and add test The https mode failed in super because BaseRequestHandler is an old-style class. This introduces the first test of https client/server functionality - and "hghave ssl". The test is currently only run on Python 2.6.
author Mads Kiilerich <mads@kiilerich.com>
date Sun, 17 Oct 2010 04:13:35 +0200
parents 8dcd3203a261
children 949dfdb3ad2d
files mercurial/hgweb/server.py tests/hghave tests/test-https.t
diffstat 3 files changed, 63 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/hgweb/server.py
+++ b/mercurial/hgweb/server.py
@@ -180,7 +180,7 @@
     def do_write(self):
         from OpenSSL.SSL import SysCallError
         try:
-            super(_shgwebhandler, self).do_write()
+            _hgwebhandler.do_write(self)
         except SysCallError, inst:
             if inst.args[0] != errno.EPIPE:
                 raise
@@ -188,7 +188,7 @@
     def handle_one_request(self):
         from OpenSSL.SSL import SysCallError, ZeroReturnError
         try:
-            super(_shgwebhandler, self).handle_one_request()
+            _hgwebhandler.handle_one_request(self)
         except (SysCallError, ZeroReturnError):
             self.close_connection = True
             pass
--- a/tests/hghave
+++ b/tests/hghave
@@ -179,12 +179,21 @@
 def has_outer_repo():
     return matchoutput('hg root 2>&1', r'')
 
+def has_ssl():
+    try:
+        from OpenSSL.SSL import SysCallError, ZeroReturnError
+        import ssl
+        return True
+    except ImportError:
+        return False
+
 checks = {
     "baz": (has_baz, "GNU Arch baz client"),
     "bzr": (has_bzr, "Canonical's Bazaar client"),
     "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
     "cvs": (has_cvs, "cvs client/server"),
     "darcs": (has_darcs, "darcs client"),
+    "docutils": (has_docutils, "Docutils text processing library"),
     "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
     "execbit": (has_executablebit, "executable bit"),
     "fifo": (has_fifo, "named pipes"),
@@ -198,7 +207,7 @@
     "outer-repo": (has_outer_repo, "outer repo"),
     "p4": (has_p4, "Perforce server and client"),
     "pygments": (has_pygments, "Pygments source highlighting library"),
-    "docutils": (has_docutils, "Docutils text processing library"),
+    "ssl": (has_ssl, "python ssl and openssl modules"),
     "svn": (has_svn, "subversion client and admin tools"),
     "svn-bindings": (has_svn_bindings, "subversion python bindings"),
     "symlink": (has_symlink, "symbolic links"),
@@ -272,5 +281,3 @@
 
     if failures != 0:
         sys.exit(1)
-
-
copy from tests/test-http.t
copy to tests/test-https.t
--- a/tests/test-http.t
+++ b/tests/test-https.t
@@ -1,5 +1,47 @@
+Proper https client requires the built-in ssl from Python 2.6,
+and https serve requires the full OpenSSL module.
 
-  $ cp "$TESTDIR"/printenv.py .
+  $ "$TESTDIR/hghave" ssl || exit 80
+
+HTTPS serve seems to be broken on Python 2.7:
+
+  $ [ "`python -c 'import sys; print sys.version_info[:2]'`" = '(2, 6)' ] || exit 80
+
+Certificates created with:
+ printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
+ openssl req -newkey rsa:512 -keyout priv.pem -nodes -x509 -days 9000 -out pub.pem
+Can be dumped with:
+ openssl x509 -in pub.pem -text
+
+  $ cat << EOT > priv.pem 
+  > -----BEGIN PRIVATE KEY-----
+  > MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApjCWeYGrIa/Vo7LH
+  > aRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8
+  > j/xgSwIDAQABAkBxHC6+Qlf0VJXGlb6NL16yEVVTQxqDS6hA9zqu6TZjrr0YMfzc
+  > EGNIiZGt7HCBL0zO+cPDg/LeCZc6HQhf0KrhAiEAzlJq4hWWzvguWFIJWSoBeBUG
+  > MF1ACazQO7PYE8M0qfECIQDONHHP0SKZzz/ZwBZcAveC5K61f/v9hONFwbeYulzR
+  > +wIgc9SvbtgB/5Yzpp//4ZAEnR7oh5SClCvyB+KSx52K3nECICbhQphhoXmI10wy
+  > aMTellaq0bpNMHFDziqH9RsqAHhjAiEAgYGxfzkftt5IUUn/iFK89aaIpyrpuaAh
+  > HY8gUVkVRVs=
+  > -----END PRIVATE KEY-----
+  > EOT
+
+  $ cat << EOT > pub.pem 
+  > -----BEGIN CERTIFICATE-----
+  > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
+  > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
+  > MTAxNDIwMzAxNFoXDTM1MDYwNTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0
+  > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
+  > ADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX
+  > 6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA+amm
+  > r24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQw
+  > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAFArvQFiAZJgQczRsbYlG1xl
+  > t+truk37w5B3m3Ick1ntRcQrqs+hf0CO1q6Squ144geYaQ8CDirSR92fICELI1c=
+  > -----END CERTIFICATE-----
+  > EOT
+  $ cat priv.pem pub.pem >> server.pem
+  $ PRIV=`pwd`/server.pem
+
   $ hg init test
   $ cd test
   $ echo foo>foo
@@ -12,46 +54,19 @@
   adding foo.d/bAr.hg.d/BaR
   adding foo.d/baR.d.hg/bAR
   adding foo.d/foo
-  $ hg serve -p $HGPORT -d --pid-file=../hg1.pid
-  $ hg --config server.uncompressed=False serve -p $HGPORT1 -d --pid-file=../hg2.pid
+  $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
+  $ cat ../hg0.pid >> $DAEMON_PIDS
 
 Test server address cannot be reused
 
-  $ hg serve -p $HGPORT1 2>&1
-  abort: cannot start server at ':$HGPORT1': Address already in use
+  $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
+  abort: cannot start server at ':$HGPORT': Address already in use
   [255]
   $ cd ..
-  $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
-
-clone via stream
-
-  $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
-  streaming all changes
-  6 files to transfer, 606 bytes of data
-  transferred * bytes in * seconds (*B/sec) (glob)
-  updating to branch default
-  4 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg verify -R copy
-  checking changesets
-  checking manifests
-  crosschecking files in changesets and manifests
-  checking files
-  4 files, 1 changesets, 4 total revisions
-
-try to clone via stream, should use pull instead
-
-  $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
-  requesting all changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 4 changes to 4 files
-  updating to branch default
-  4 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 clone via pull
 
-  $ hg clone http://localhost:$HGPORT1/ copy-pull
+  $ hg clone https://localhost:$HGPORT/ copy-pull
   requesting all changes
   adding changesets
   adding manifests
@@ -75,10 +90,10 @@
 
   $ cd copy-pull
   $ echo '[hooks]' >> .hg/hgrc
-  $ echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
+  $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
   $ hg pull
-  changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=http://localhost:$HGPORT1/ 
-  pulling from http://localhost:$HGPORT1/
+  changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/ 
+  pulling from https://localhost:$HGPORT/
   searching for changes
   adding changesets
   adding manifests