[PATCH] Keep authentication information after the first fail HTTP access (issue3567)
Stéphane Klein
sklein at bearstech.com
Mon Dec 30 14:27:09 UTC 2013
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
# HG changeset patch
# User Stéphane Klein <contact at stephane-klein.info>
# Date 1388413356 -3600
# Mon Dec 30 15:22:36 2013 +0100
# Node ID 9063db5432d6c6c75491e759861a373bc493822a
# Parent 4274eda143cb1025be1130ffdaaf62370a2a6961
Keep authentication information after the first fail HTTP access (issue3567)
Context : mercurial access to repository server with http access, and this
server is protected by basic auth.
Before patch :
* mercurial try an anonymous access to server, server return 401 response and
mercurial resend request with login / password information
After patch :
* mercurial try an anonymous access to server, server return
401 response. For all next requests, mercurial keep in memory this
information (this server need basic auth information).
This patch reduce the number of http access against mercurial server.
Example, before patch :
10.10.168.170 - - [25/Oct/2013:15:44:51 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:44:52 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:00 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:01 +0200] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:03 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:04 +0200] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:06 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:07 +0200] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:09 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:10 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [25/Oct/2013:15:45:12 +0200] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"
Example after patch :
10.10.168.170 - - [28/Oct/2013:11:49:14 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 401 260 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:15 +0100] "GET /hg/testagt?cmd=capabilities
HTTP/1.1" 200 147 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:17 +0100] "GET /hg/testagt?cmd=batch
HTTP/1.1" 200 42 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:19 +0100] "GET /hg/testagt?cmd=getbundle
HTTP/1.1" 200 61184 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:22 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 15 "-" "mercurial/proto-1.0"
10.10.168.170 - - [28/Oct/2013:11:49:24 +0100] "GET /hg/testagt?cmd=listkeys
HTTP/1.1" 200 - "-" "mercurial/proto-1.0"
In this last example, you can see only one 401 response.
diff -r 4274eda143cb -r 9063db5432d6 mercurial/url.py
- --- a/mercurial/url.py Mon Sep 16 01:08:29 2013 -0700
+++ b/mercurial/url.py Mon Dec 30 15:22:36 2013 +0100
@@ -8,6 +8,7 @@
# GNU General Public License version 2 or any later version.
import urllib, urllib2, httplib, os, socket, cStringIO
+import base64
from i18n import _
import keepalive, util, sslutil
import httpconnection as httpconnectionmod
@@ -418,9 +419,22 @@
class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
def __init__(self, *args, **kwargs):
+ self.auth = None
urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
self.retried_req = None
+ def http_request(self, request):
+ if self.auth:
+ request.add_unredirected_header(self.auth_header, self.auth)
+
+ return request
+
+ def https_request(self, request):
+ if self.auth:
+ request.add_unredirected_header(self.auth_header, self.auth)
+
+ return request
+
def reset_retry_count(self):
# Python 2.6.5 will call this on 401 or 407 errors and thus loop
# forever. We disable reset_retry_count completely and reset in
@@ -435,6 +449,19 @@
return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
self, auth_header, host, req, headers)
+ def retry_http_basic_auth(self, host, req, realm):
+ user, pw = self.passwd.find_user_password(realm, req.get_full_url())
+ if pw is not None:
+ raw = "%s:%s" % (user, pw)
+ auth = 'Basic %s' % base64.b64encode(raw).strip()
+ if req.headers.get(self.auth_header, None) == auth:
+ return None
+ self.auth = auth
+ req.add_header(self.auth_header, auth)
+ return self.parent.open(req)
+ else:
+ return None
+
handlerfuncs = []
def opener(ui, authinfo=None):
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iF4EAREIAAYFAlLBgr0ACgkQU9O4HJsr4YyHrgD8D53D5ch3lXNMBY6u06MMCUL3
Di2nnU+ozINRP4hS56UA/RKm7kf4eUzcXBkUaI/wxYB0SL4Z5h3tNrEsYSk9SQyZ
=AFUv
-----END PGP SIGNATURE-----
More information about the Mercurial-devel
mailing list