2011-12-15 19 views
8

Estoy jugando con la API de Google Checkout y quiero incorporarlo a una aplicación de Django. Necesito publicar datos en Google usando autenticación http básica. He estado probando esto con curl así:Publicar datos sin procesar con Python

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

Y que los puestos del contenido de mi prueba del archivo XML para Google. Y funciona bien!

Pero estoy teniendo problemas para portar esa línea simple a Python. He manejado varias formas diferentes (httplib2, urllib2, pycurl) de conectar con una contraseña y publicar algo, pero la resposición es siempre 400 MALA PETICIÓN.

¿Hay un equivalente de python para publicar el bloque de texto en un servidor de autenticación HTTP básica? Me estoy quedando sin paredes para golpearme la cabeza.


Disculpa por no agregar ningún código. Estos son algunos de mis mejores éxitos. En cada uno, DATA es una cadena XML. URL, USERNAME y PASSWORD son constantes.

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

me da una preciosa 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) 

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

parece luchar con el paso de la cadena DATA como POSTFIELD . He intentado urllib.urlencode() DATOS ción de varias maneras diferentes, pero


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

no parecen hacer nada Las credenciales - Me aparece un mensaje no autorizado detrás de Google.

Hay más, pero todos están basados ​​en estos.

Respuesta

12

He tenido desórdenes similares con los paquetes stdlib, hasta que alguien señaló el impresionante requests que admite la Autenticación Http básica y otros medios de autenticación directamente ¡listos para usar! ¡Y tiene una API hermosa y simple que duele!

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

Es compatible con una serie de otras características necesarias (por ejemplo HTTPS, autenticación Digest, etc.) Por favor, echa un vistazo si u debe ...

2

Voidspace tiene an excellent article en el uso de la autenticación básica con urllib2. He copiado el fragmento de código apropiado a continuación, modificado para usar 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()) 

Sin ver su código es difícil decir por qué recibiría una respuesta de 400.

+0

Estoy de acuerdo! Es muy difícil saber qué he intentado si no te cuento. Mis disculpas. Ahora tengo los principales grupos de métodos (probablemente tenga alrededor de 5 permutaciones para cada "método"). Con este método no estaba autorizando. No parecía que Password Manager estaba haciendo nada. Pero he arreglado 'httplib2' ahora (tal como se publicó) así que con suerte no tendré que usar otro método para esto. – Oli

2

Durante la edición de mi post para incluir alguna fuente, yo pensé que tendría otra oportunidad (principalmente porque es relativamente pequeño y bonito en comparación con los otros) y se dio cuenta de que hay a gaping bug en que su método add_credentials(..) en realidad no hacer nada. Puede solucionar esto especificando la cabecera (como lo hice con urllib2) así:

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

Y esto funciona.

Cuestiones relacionadas