【问题标题】:Posting raw data with Python使用 Python 发布原始数据
【发布时间】:2012-01-21 03:20:10
【问题描述】:

我正在使用 Google Checkout API,我想将它放入 Django 应用程序中。我需要使用基本的 http 身份验证将数据发布到 Google。我一直在使用curl 进行测试,如下所示:

curl -d "$(cat mytest.xml)" -u username:password https://url

这会将我的测试 XML 文件的内容发布到 Google。而且效果很好!

但我在将那条简单的行移植到 Python 时遇到了问题。我已经管理了几种不同的方式(httplib2、urllib2、pycurl)来连接密码并发布一些东西,但响应总是 400 BAD REQUEST。

是否有一个 python 等价于将文本块发布到 HTTP 基本身份验证服务器?我的头都快用完了。


很抱歉没有添加任何代码。这是我的一些最热门的歌曲。在每个中,DATA 是一个 XML 字符串。 URLUSERNAMEPASSWORD 是常量。

req = urllib2.Request(URL)
req.add_header("Authorization", "Basic %s" % base64.encodestring('%s:%s'%(USERNAME, PASSWORD)))
u = urllib2.urlopen(req, DATA)

给我一​​个可爱的HTTP Error 400: Bad Request


passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, URL, USERNAME, PASSWORD)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
pagehandle = urllib2.urlopen(URL, DATA)

HTTP Error 401: Unauthorized


pycurl.global_init(pycurl.GLOBAL_DEFAULT)
c = pycurl.Curl()
c.setopt(pycurl.URL, URL)
c.setopt(pycurl.USERPWD, "%s:%s" % (USERNAME,PASSWORD))
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"])
c.setopt(pycurl.POSTFIELDS, DATA)
b = StringIO.StringIO()
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.perform()

似乎很难将 DATA 字符串作为 POSTFIELD 传递。我用几种不同的方式尝试了urllib.urlencode()ing DATA,但是


h = httplib2.Http()
h.add_credentials(USERNAME, PASSWORD)
print = h.request(URL, "POST", body=base64.encodestring(DATA))

凭据似乎没有任何作用 - 我收到了来自 Google 的未经授权的消息。

还有更多,但它们都基于这些。

【问题讨论】:

    标签: python post curl urllib2 pycurl


    【解决方案1】:

    我对 stdlib 包也有过类似的困扰,直到 somoneone 指出了支持基本 Http 身份验证和其他直接开箱即用的身份验证方式的 requests!而且它有一个漂亮而简单的 API,这很伤人!

    requests.post(url, data=DATA, headers=HEADERS_DICT, auth=(username, password))
    

    它支持许多其他必要的功能(例如 HTTPS、摘要式身份验证等)如果你必须检查它...

    【讨论】:

      【解决方案2】:

      Voidspace 有an excellent article 使用 urllib2 的基本身份验证。我在下面复制了相应的代码 sn-p,改为使用 POST。

      import urllib2
      
      theurl = 'http://www.someserver.com/toplevelurl/somepage.htm'
      username = 'johnny'
      password = 'XXXXXX'
      
      passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
      passman.add_password(None, theurl, username, password)
      
      authhandler = urllib2.HTTPBasicAuthHandler(passman)
      
      opener = urllib2.build_opener(authhandler)
      
      urllib2.install_opener(opener)
      
      pagehandle = urllib2.urlopen(theurl, open("mytext.xml").read())
      

      如果没有看到您的代码,很难说出为什么会收到 400 响应。

      【讨论】:

      • 我同意!如果我不告诉你,很难知道我尝试过什么。我很抱歉。我现在有主要的方法组(每个“方法”我可能有大约 5 个排列)。使用这种方法,它没有被授权。密码管理器似乎没有做任何事情。但是我现在已经修复了httplib2(如发布的那样),所以希望不必为此使用其他方法。
      【解决方案3】:

      在编辑我的帖子以包含一些来源时,我想我会在httplib2 有另一个破解(主要是因为它与其他人相比相对较小且漂亮)并注意到有a gaping bug 在它的add_credentials(..)方法实际上并没有做任何事情。您可以通过指定标头(就像我对 urllib2 所做的那样)来解决此问题,如下所示:

      resp, content = httplib2.Http().request(URL, "POST", body=DATA, headers={
          "Authorization": "Basic %s" % base64.encodestring('%s:%s' %(USERNAME, PASSWORD)
      })
      

      这行得通。

      【讨论】:

        猜你喜欢
        • 2017-06-17
        • 2013-01-24
        • 2017-08-20
        • 2020-11-14
        • 2020-10-12
        • 1970-01-01
        • 2022-08-14
        • 2011-05-18
        • 1970-01-01
        相关资源
        最近更新 更多