[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