[Python-Dev] [issue19494] Problems with HTTPBasicAuthHandler

Matej Cepl mcepl at redhat.com
Thu Nov 21 00:08:30 CET 2013


I am trying to work on fixing issue 19494 (HTTPBasicAuthHandler 
doesn't work with Github and other websites which require prior 
Authorization header in the first request).

I have created this testing script calling GitHub v3 API using 
new “authentication handlers” (they are subclasses of 
HTTPSHandler, not HTTPBasicAuthHandler) and hoped that when 
I manage to make this script working, I could rewrite it into 
patch against cpython code.

However, when I run this script I get this error (using 

matej at wycliff: $ python3 test_create_1.py 
DEBUG:<module>:gh_url = https://api.github.com/repos/mcepl/odt2rst/issues/
DEBUG:<module>:req = <urllib.request.Request object at 0x7fee384a9fd0>
DEBUG:<module>:req.type = https
DEBUG:http_request:type = https
Traceback (most recent call last):
  File "test_create_1.py", line 80, in <module>
    handler = opener.open(req, json.dumps(create_data).encode('utf8'))
  File "/usr/lib64/python3.3/urllib/request.py", line 475, in open
    response = meth(req, response)
  File "/usr/lib64/python3.3/urllib/request.py", line 587, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib64/python3.3/urllib/request.py", line 513, in error
    return self._call_chain(*args)
  File "/usr/lib64/python3.3/urllib/request.py", line 447, in _call_chain
    result = func(*args)
  File "/usr/lib64/python3.3/urllib/request.py", line 595, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 401: Unauthorized
matej at wycliff: $ 

Could anybody suggest what I am doing wrong? I guess I need to 
somehow include into opener original HTTPBasicAuthHandler (for 
error handlers). Any ideas how to do it?


Matěj Cepl

http://www.ceplovi.cz/matej/, Jabber: mcepl<at>ceplovi.cz
GPG Finger: 89EF 4BC6 288A BF43 1BAB  25C3 E09F EF25 D964 84AC
- Do you think of yourself as a Christian artist?
- I'm an artist who is a Christian. I'm not a Christian artist.
      -- Johny Cash
         in his last interview

import base64
import http.client
import urllib.request
import json
import os
import logging
from configparser import ConfigParser

class HTTPBasicPriorAuthHandler(urllib.request.HTTPHandler):
    handler_order = 400

    def __init__(self, *args, **kwargs):
        passwd_mgr = kwargs.pop('password_mgr', None)
        urllib.request.HTTPHandler.__init__(self, *args, **kwargs)
        self.passwd = passwd_mgr

    def http_request(self, req):
        logging.debug("type = {}".format(req.type))
        if not req.has_header('Authorization'):
            user, passwd = self.passwd.find_user_password(
                None, req.get_full_url())
            auth_str = base64.standard_b64encode(
                '{}:{}'.format(user, passwd).encode('ascii'))
                           'Basic {}'.format(auth_str))
        return urllib.request.AbstractHTTPHandler.do_request_(self, req)

if hasattr(http.client, 'ssl'):
    handler_order = 400

    class HTTPSBasicPriorAuthHandler(urllib.request.HTTPSHandler):
        def __init__(self, *args, **kwargs):
            passwd_mgr = kwargs.pop('password_mgr', None)
            urllib.request.HTTPSHandler.__init__(self, *args, **kwargs)
            self.passwd = passwd_mgr

        https_request = HTTPBasicPriorAuthHandler.http_request

cp = ConfigParser()

# That configuration file should look something like
# [github]
# user=mylogin
# password=myveryverysecretpassword

gh_user = cp.get('github', 'user')
gh_passw = cp.get('github', 'password')
repo = 'odt2rst'

pwd_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
pwd_manager.add_password(None, uri='https://api.github.com', user=gh_user,
auth_prior_handler = HTTPSBasicPriorAuthHandler(password_mgr=pwd_manager)

auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr=pwd_manager)

opener = urllib.request.build_opener(auth_prior_handler, auth_handler)

API_URL = "https://api.github.com/repos/{0}/{1}/issues/"
gh_url = API_URL.format(gh_user, repo, 1)

logging.debug("gh_url = {0}".format(gh_url))
req = urllib.request.Request(gh_url)
logging.debug('req = {}'.format(req))
logging.debug('req.type = {}'.format(req.type))

create_data = {
    'title': 'Testing bug summary',
    'body': '''This is a testing bug. I am writing here this stuff,
            just to have some text for body.''',
    'labels': ['BEbug']

handler = opener.open(req, json.dumps(create_data).encode('utf8'))

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20131121/cfdf799e/attachment.sig>

More information about the Python-Dev mailing list