使用Python发布原始数据

9

我正在尝试使用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错误400:错误请求


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错误401:未经授权”


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))

凭据好像没有起到任何作用- 我从谷歌收到了未经授权的信息。 还有其他的,但都是基于这些东西。
3个回答

12

我一直在使用Python标准库的包时遇到类似的问题,直到有人指向了很棒的requests,它支持基本的HTTP身份验证和其他身份验证方式,而且API简单易用!使用它真是太舒服了!

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

它支持许多其他必要功能(例如HTTPS、摘要身份验证等)。如果必须,请查看它...


2

Voidspace有一篇关于使用urllib2进行基本身份验证的优秀文章。我在下面复制了适当的代码片段,并更改为使用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(如发布的),所以希望不必再使用另一种方法。 - Oli

2

在编辑我的帖子时,我想再试一下httplib2(主要是因为相对于其他库它比较小巧精致),并发现它存在一个严重的漏洞,即其add_credentials(..)方法实际上没有任何作用。你可以通过像这样指定头部(就像我使用urllib2一样)来解决这个问题:

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

而且这个有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接