[PATCH] Keep authentication information after the first fail HTTP access (issue3567)

Augie Fackler raf at durin42.com
Sat Dec 14 11:49:39 CST 2013


Aaaand I just backed it out, thanks to terrible breakage on Python 2.4.

Sigh. Patch works great on 2.6 and 2.7, disaster on 2.4.

On Dec 13, 2013, at 12:48 PM, Augie Fackler <raf at durin42.com> wrote:

> On Tue, Dec 10, 2013 at 04:22:39PM -0500, Augie Fackler wrote:
>> On Mon, Nov 25, 2013 at 05:22:10PM +0100, Stéphane Klein wrote:
>>> # HG changeset patch
>>> # User Stéphane Klein <contact at stephane-klein.info>
>>> # Date 1385396292 -3600
>>> #      Mon Nov 25 17:18:12 2013 +0100
>>> # Node ID ec1afe2354a840eb47a2286308fb5a5eeed91eba
>>> # Parent  1c46b18b0e1c47fa4cecf21b78c083a54ae9903f
>>> Keep authentication information after the first fail HTTP access (issue3567)
>> 
>> Hearing no objections after a couple of weeks, I'm queueing this. It
>> seems reasonable.
> 
> (but, I should mention, with some tweaks to the log message to make it
> more compliant with our format and a minor English tweak)
> 
>> 
>>> 
>>> 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 1c46b18b0e1c -r ec1afe2354a8 mercurial/url.py
>>> --- a/mercurial/url.py    Fri Nov 22 17:26:58 2013 -0600
>>> +++ b/mercurial/url.py    Mon Nov 25 17:18:12 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, host)
>>> +        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_unredirected_header(self.auth_header, auth)
>>> +            return self.parent.open(req, timeout=req.timeout)
>>> +        else:
>>> +            return None
>>> +
>>> handlerfuncs = []
>>> 
>>> def opener(ui, authinfo=None):
>>> 
>>> --
>>> Stéphane Klein <sklein at bearstech.com>
>>> GSM : 06 61 48 76 04
>>> 
>>> _______________________________________________
>>> Mercurial-devel mailing list
>>> Mercurial-devel at selenic.com
>>> http://selenic.com/mailman/listinfo/mercurial-devel
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at selenic.com
>> http://selenic.com/mailman/listinfo/mercurial-devel
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20131214/c7832ec5/attachment.pgp>


More information about the Mercurial-devel mailing list