[PATCH] Keep authentication information after the first fail HTTP access (issue3567)
Augie Fackler
raf at durin42.com
Tue Dec 10 21:22:39 UTC 2013
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.
>
> 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
More information about the Mercurial-devel
mailing list