2011-12-15 16 views
8

Używam interfejsu API usługi Google Checkout i chcę go pobrać do aplikacji Django. Chcę przesłać dane do Google przy użyciu podstawowego uwierzytelniania http. Byłem testowania to z curl tak:Wysyłanie nieprzetworzonych danych za pomocą Pythona

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

I że posty treścią mojego testowego pliku XML do Google. I działa dobrze!

Ale mam problemy z przeniesieniem prostej linii do Pythona. Udało mi się na kilka różnych sposobów (httplib2, urllib2, pycurl) połączyć się z hasłem i opublikować coś, ale kwestia ta wynosi zawsze 400 ZŁE ŻĄDANIE.

Czy istnieje odpowiednik w języku Python do publikowania bloku tekstu na serwerze uwierzytelniania HTTP Basic? Kończy mi się ściana, żeby uderzyć głową w moją głowę.


Przepraszam, że nie dodano żadnego kodu. Oto niektóre z moich największych przebojów. W każdym z nich DATA jest ciągiem XML. URL, USERNAME i PASSWORD są stałe.

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

daje mi piękny 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) 

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

Wydaje walczyć z przechodzącej ciąg DATA jako POSTFIELD . Próbowałem urllib.urlencode() DANE ING w kilku różnych sposobów, ale


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

Poświadczenia zdają się nie robić nic - ja uzyskać nieautoryzowany wiadomość z powrotem z Google.

Jest ich więcej, ale wszystkie opierają się na tych.

Odpowiedz

12

Miałem podobne zawirowania z pakietami stdlib, dopóki nikt nie wskazał na niesamowitą requests, która obsługuje podstawowe uwierzytelnianie HTTP i inne metody uwierzytelniania prosto z zestawu! I ma piękny i prosty interfejs API, który boli!

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

Obsługuje wiele innych niezbędnych funkcji (np HTTPS, uwierzytelnianie Digest, itp) Proszę to sprawdzić, czy u musi ...

2

Voidspace ma an excellent article na korzystanie z podstawowego uwierzytelniania z urllib2. Skopiowałem odpowiedni fragment kodu poniżej, zmieniony tak, aby używał 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()) 

Bez zobaczenia kodu trudno powiedzieć, dlaczego otrzymujesz odpowiedź 400.

+0

zgadzam! Bardzo trudno jest wiedzieć, co próbowałem, jeśli ci nie powiem. Przepraszam. Mam teraz główne grupy metod (prawdopodobnie mam około 5 permutacji dla każdej "metody"). Dzięki tej metodzie nie autoryzował. Wyglądało na to, że Menedżer haseł nic nie robił. Ale naprawiłem 'httplib2' teraz (jako wysłany), więc mam nadzieję, że nie będziemy musieli użyć innej metody. – Oli

2

Podczas edycji mój post na to jakieś źródło, pomyślałem, że mam inny trzask na (głównie dlatego, że jest stosunkowo mała i dość w porównaniu do innych) i zauważyłem, że jest a gaping bug tym, że jego metoda add_credentials(..) rzeczywistości nie Zrób cokolwiek. Można obejść ten problem poprzez określenie nagłówka (jak ja z urllib2) tak:

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

I to działa.

Powiązane problemy