使用Python发布原始数据

时间:2011-12-15 12:10:03

标签: python post curl urllib2 pycurl

我正在使用Google Checkout API,我想将其拉入Django应用程序。我需要使用基本的http身份验证将数据发布到Google。我一直用curl测试这个:

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

并将我的测试XML文件的内容发布到Google。它工作正常!

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

是否有用于将文本块发布到HTTP Basic auth服务器的python等效项?我跑出墙壁撞到我的脑袋。


不添加任何代码的道歉。以下是我最热门的一些热门话题。在每个中,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() DATA,但是


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

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

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

3 个答案:

答案 0 :(得分:12)

我一直在使用stdlib包进行类似的混乱,直到somoneone指向支持基本Http身份验证的真棒requests,其他身份验证意味着开箱即用!它有一个美丽而简单的API,它很痛!

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

它支持许多其他必要功能(例如HTTPS,摘要式身份验证等)请检查一下是否必须...

答案 1 :(得分:2)

Voidspace在使用urllib2的基本身份验证时已an excellent article。我已经复制了下面相应的代码段,更改为使用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响应。

答案 2 :(得分:2)

在编辑我的帖子以包含一些来源时,我认为我会在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)
})

这很有效。