代码之家  ›  专栏  ›  技术社区  ›  Martin Del Vecchio

fancyurlopener、401和“连接:关闭”的python问题

  •  2
  • Martin Del Vecchio  · 技术社区  · 15 年前

    我是python新手,如果我遗漏了一些显而易见的东西,请原谅我。

    我正在使用urllib.fancyurlopener检索web文档。在Web服务器上禁用身份验证时,它工作正常,但在启用身份验证时失败。

    我的猜测是,我需要子类urllib.fancyurlopener来覆盖get_user_passwd()和/或prompt_user_passwd()方法。所以我做到了:

    class my_opener (urllib.FancyURLopener):
    
        # Redefine
        def get_user_passwd(self, host, realm, clear_cache=0):
            print "get_user_passwd() called; host %s, realm %s" % (host, realm)
            return ('name', 'password')
    

    然后我试图打开页面:

    try:
        opener = my_opener()
        f = opener.open ('http://1.2.3.4/whatever.html')
        content = f.read()
        print "Got it:  ", content
    
    except IOError:
        print "Failed!"
    

    我希望fancyurlopener处理401,调用我的get_user_passwd(),然后重试请求。

    它没有;我在调用“f=opener.open()”时得到ioerror异常。

    wireshark告诉我请求已发送,服务器正在发送一个“401未授权”响应,其中包含两个感兴趣的头:

    WWW-Authenticate: BASIC
    Connection: close
    

    然后连接关闭,我发现异常,一切都结束了。

    即使我在ioerror之后重试“f=opener.open()”,它也会以同样的方式失败。

    我已经用一个简单的“print‘got 401 error’”重写了http_error_401()方法,从而验证了我的_opener()类是否工作正常。我还试图重写prompt_user_passwd()方法,但这也不会发生。

    我看不到主动指定用户名和密码的方法。

    那么如何让urllib重试请求呢?

    谢谢。

    1 回复  |  直到 15 年前
        1
  •  0
  •   nurio    13 年前

    我刚刚在我的web服务器(nginx)上尝试了你的代码,它按预期工作:

    • 从urllib客户端获取
    • http/1.1 401未经授权从带有头的服务器

      Connection: close
      WWW-Authenticate: Basic realm="Restricted"
      
    • 客户端使用授权头重试

      Authorization: Basic <Base64encoded credentials>
      
    • 服务器响应200个OK+内容

    所以我猜你的代码是对的(我用Python2.7.1试过了),也许你试图访问的Web服务器没有按预期工作。下面是使用免费的http basic auth testsite browserspy.dk测试的代码(似乎他们正在使用apache-代码按预期工作):

    import urllib
    
    class my_opener (urllib.FancyURLopener):
    
        # Redefine
        def get_user_passwd(self, host, realm, clear_cache=0):
            print "get_user_passwd() called; host %s, realm %s" % (host, realm)
            return ('test', 'test')
    
    try:
        opener = my_opener()
        f = opener.open ('http://browserspy.dk/password-ok.php')
        content = f.read()
        print "Got it:  ", content
    
    except IOError:
        print "Failed!"