2011-12-15 4 views
8

Я играю с API Google Checkout, и я хочу поместить его в приложение Django. Мне нужно отправить данные в Google, используя базовую HTTP-аутентификацию. Я тестировал это с curl как это:Проводка необработанных данных с помощью Python

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

И что посты содержание моего тестового файла XML в Google. И все отлично!

Но у меня возникают проблемы с переносом этой простой строки на Python. Мне удалось несколько разных способов (httplib2, urllib2, pycurl) подключиться к паролю и отправить что-то, но респоз всегда 400 ЗАПРЕЩЕН.

Есть ли эквивалент python для отправки блока текста на базовый сервер аутентификации HTTP? Я бегу от стен, чтобы ударить головой.


Извините, если не добавить код. Вот некоторые из моих лучших хитов. В каждом из них DATA является XML-строкой. URL, USERNAME и PASSWORD являются постоянными.

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.

Есть больше, но все они основаны на них.

ответ

12

У меня были подобные турмусы с пакетами stdlib, пока тот не указал на удивительный requests, который поддерживает базовую аутентификацию Http и другую аутентификацию прямо из коробки! И у этого есть красивый и простой API, он болит!

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

Он поддерживает множество других необходимых функций (например HTTPS, Digest Authentication и т.д.) Пожалуйста, проверьте его, если и надо ...

2

Voidspace имеет an excellent article при использовании базового auth с 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.

+0

Я согласен! Очень трудно понять, что я пробовал, если не скажу. Мои извинения. Сейчас у меня есть основные группы методов (у меня, вероятно, есть около 5 перестановок для каждого «метода»). С помощью этого метода он не разрешал. Не было похоже, что Менеджер паролей ничего не делал. Но я исправил 'httplib2' сейчас (как опубликовано), поэтому, надеюсь, не придется использовать для этого другой метод. – Oli

2

При редактировании мой пост, чтобы включить какой-то источник, я думал, что есть еще одна трещина в (в основном потому, что это сравнительно небольшой и довольно по сравнению с другими) и заметил, что есть 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) 
}) 

И это работает.