2011-06-10 17 views
7

Actualmente estoy trabajando con un código escrito por otra persona. Utiliza httplib para realizar solicitudes al servidor. Tiene todos los datos proporcionados en un formato correcto, por ejemplo cuerpo de mensaje, valores de encabezado, etc.Python httplib y POST

El problema es que cada vez que intenta enviar una solicitud POST, la información está allí - Puedo verla en el lado del cliente, sin embargo, nada llega al servidor. He leído las especificaciones de la biblioteca y el uso parece ser correcto.

Las llamadas a las bibliotecas extraídos ser la siguiente:

import httplib 

conn = httplib.HTTPConnection('monkeylabs.pl', 80) 
conn.connect() 
request = conn.putrequest('POST', '/api/snippet/') 
headers = {} 
headers['Content-Type'] = 'application/json' 
headers['User-Agent'] = 'Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic; pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03' 
headers['Accept'] = '*/*' 
for k in headers: 
    conn.putheader(k, headers[k]) 
conn.endheaders() 

conn.send('[{"id":"route"}]') 

resp = conn.getresponse() 
print resp.status 
print resp.reason 
print resp.read() 

conn.close() 

Es esto algún problema conocido, o qué? Estoy usando Python 2.7. No estoy seguro de cómo verificar la versión de httplib.

Por favor no sugiera intercambiar httplib por otra cosa a menos que sea algo realmente similar (httplib2 quizás). Como dije, el código no es mío y viene en cantidades mucho mayores que las que acabo de publicar. Refactorizarlo causaría un problema importante. Estoy interesado en cualquier solución alternativa confiable.

EDITAR

El resultado de la depuración:

send: 'POST /api/snippet/ HTTP/1.1\r\nHost: monkeylabs.pl\r\nAccept-Encoding: identity\r\nContent-Type: application/json\r\nAccept: */*\r\nUser-Agent: Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic; pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03\r\n\r\n[{"id":"route"}]' 
reply: 'HTTP/1.0 201 CREATED\r\n' 
header: Date: Fri, 10 Jun 2011 23:54:00 GMT 
header: Server: WSGIServer/0.1 Python/2.7.1+ 
header: Vary: Cookie 
header: Content-Type: application/json 
header: Content-Length: 0 
201 
CREATED 

Tenga en cuenta que la información después de respuesta en realidad habla sobre la respuesta del servidor, no la propia solicitud, que en este caso está vacía. La causa principal es que el cuerpo de la petición en sí es vacío, que puedo observar al obtener un registro:

[11/Jun/2011 01:54:00] "POST /api/snippet/ HTTP/1.1" 201 0 

Y esas tres líneas:

`` 
<QueryDict: {}> 
<QueryDict: {}> 

de:

print '`%s`' % request.raw_post_data 
print request.GET 
print request.POST 

en el servidor Django. Parece que intenta enviar el cuerpo pero no lo envía al final.

EDITAR (2)

Ok, me tomó un basurero y que de hecho me dijeron que en el mensaje enviado desde el navegador hay un parámetro adicional denominado 'Content-Length' que se ha omitido en el uso regular de la biblioteca. Tonto de mí.

+2

Por cierto, si usted piensa que va a depurando esta cosa mucho, instalar [Wireshark] (http://www.wireshark.org/) y lo usa para espiar lo que está pasando por el cable. – Darien

+0

Gracias, al principio no era creyente, pero en realidad me condujo a la solución. Gracias de nuevo – julkiewicz

+0

El servidor tiene: response.set_header ('Access-Control-Allow-Origin', '*') ???? –

Respuesta

5

intento de añadir:

conn.set_debuglevel(1) 

a su código para que pueda ver lo que está sucediendo realmente.

0

¿Ha comprobado la documentación de httplib? httplib es una biblioteca estándar de Python y Python también es muy bueno de tener la documentación en línea: http://docs.python.org/library/httplib.html

El ejemplo de esa página:

>>> import httplib, urllib 
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) 
>>> headers = {"Content-type": "application/x-www-form-urlencoded", 
...   "Accept": "text/plain"} 
>>> conn = httplib.HTTPConnection("musi-cal.mojam.com:80") 
>>> conn.request("POST", "/cgi-bin/query", params, headers) 
>>> response = conn.getresponse() 
>>> print response.status, response.reason 
200 OK 
>>> data = response.read() 
>>> conn.close() 

Su ejemplo parece ser más trabajo que esto, y si se lee la documentación de la API, por ejemplo para putrequest, verá que la está utilizando mal en su muestra. Específicamente, agrega automáticamente el encabezado Aceptar de forma predeterminada.

Intenta hacer que tu código se parezca más al ejemplo funcional, también intenta comprender las llamadas utilizadas tanto en tu código como en el ejemplo de trabajo.

+1

Sí, leí la documentación de la API y todo parece estar bien. El problema es que no está bien. La misma solicitud hecha por otros medios, por ejemplo, un navegador u otra biblioteca funciona bien. La eliminación del encabezado 'Aceptar' no cambia nada. El ejemplo que copia pegado de la API es simplemente hacer algo totalmente diferente. No es un POST y no intenta cargar el cuerpo del mensaje. – julkiewicz

6

El método putrequest no agrega automáticamente el encabezado Content Length, tiene que hacerlo usted mismo o usar el método request.

Agregue esto a su código del bucle for:

headers['Content-Length'] = "%d"%(len('[{"id":"route"}]'))