2011-12-15 10 views
8

Sto giocando con l'API di Google Checkout e voglio inserirli in un'app di Django. Devo pubblicare i dati su Google utilizzando l'autenticazione HTTP di base. Ho testato questo con curl come questo:Pubblicazione di dati grezzi con Python

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

E che i posti il ​​contenuto della mia prova file XML di Google. E funziona bene!

Ma sto riscontrando problemi nel porting di quella semplice linea a Python. Ho gestito diversi modi (httplib2, urllib2, pycurl) di connettermi con una password e pubblicare qualcosa ma il respose è sempre 400 BAD REQUEST.

Esiste un equivalente python per la pubblicazione di blocchi di testo su un server di autenticazione HTTP di base? Sto correndo fuori dai muri per sbattere la testa contro.


Scuse per non aggiungere alcun codice. Ecco alcuni dei miei più grandi successi. In ciascuno, DATA è una stringa XML. URL, USERNAME e PASSWORD sono costanti.

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

mi dà un bel 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() 

sembra lottare con passando la stringa DATA come POSTFIELD . Ho provato urllib.urlencode() ing DATI in molti modi diversi, ma


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

Le credenziali non sembrano fare nulla - ricevo un messaggio non autorizzata di ritorno da Google.

Ce ne sono di più, ma sono tutti basati su questi.

risposta

12

Ho avuto simili turbolenze con i pacchetti stdlib, fino a quando somoneone ha indicato il fantastico requests che supporta l'autenticazione Http di base e altri mezzi di autenticazione subito pronti all'uso! E ha un'API bella e semplice che fa male!

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

Supporta una serie di altre caratteristiche necessarie (per esempio HTTPS, l'autenticazione Digest, ecc) Si prega di verificare se u deve ...

2

Spazio vuoto ha an excellent article sull'autorizzazione di base con urllib2. Ho copiato lo snippet di codice appropriato di seguito, modificato per utilizzare 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()) 

Senza vedere il codice è difficile dire perché si sarebbe trovato una risposta 400.

+0

Sono d'accordo! È molto difficile sapere cosa ho provato se non te lo dico. Mie scuse. Ora ho i principali gruppi di metodi (probabilmente ho ottenuto circa 5 permutazioni per ogni "metodo"). Con questo metodo non stava autorizzando. Non sembrava che il gestore delle password stesse facendo qualcosa. Ma ho corretto 'httplib2' ora (come pubblicato) quindi spero non dovremo usare un altro metodo per questo. – Oli

2

Durante la modifica il mio post per includere qualche fonte, ho pensato che avrei avuto un'altra crepa al (soprattutto perché è relativamente piccolo e grazioso rispetto agli altri) e ho notato che c'è a gaping bug in quel suo metodo add_credentials(..) in realtà non Fai qualcosa. È possibile aggirare questo specificando l'intestazione (come ho fatto con urllib2) come questo:

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

E questo funziona.

Problemi correlati