¿Cómo puedo ver toda la solicitud HTTP que envía mi aplicación Python?

263

En mi caso, estoy usando la requestsbiblioteca para llamar a la API de PayPal a través de HTTPS. Desafortunadamente, recibo un error de PayPal, y el soporte de PayPal no puede determinar cuál es el error o qué lo está causando. Quieren que "proporcione la solicitud completa, incluidos los encabezados".

¿Cómo puedo hacer eso?

Chris B.
fuente

Respuestas:

499

Un método simple: habilitar el registro en versiones recientes de Solicitudes (1.xy superior).

Requests utiliza la configuración del módulo http.clienty loggingpara controlar la verbosidad del registro, como se describe aquí .

Demostración

Código extraído de la documentación vinculada:

import requests
import logging

# These two lines enable debugging at httplib level (requests->urllib3->http.client)
# You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
# The only thing missing will be the response.body which is not logged.
try:
    import http.client as http_client
except ImportError:
    # Python 2
    import httplib as http_client
http_client.HTTPConnection.debuglevel = 1

# You must initialize logging, otherwise you'll not see debug output.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

requests.get('https://httpbin.org/headers')

Salida de ejemplo

$ python requests-logging.py 
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): httpbin.org
send: 'GET /headers HTTP/1.1\r\nHost: httpbin.org\r\nAccept-Encoding: gzip, deflate, compress\r\nAccept: */*\r\nUser-Agent: python-requests/1.2.0 CPython/2.7.3 Linux/3.2.0-48-generic\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json
header: Date: Sat, 29 Jun 2013 11:19:34 GMT
header: Server: gunicorn/0.17.4
header: Content-Length: 226
header: Connection: keep-alive
DEBUG:requests.packages.urllib3.connectionpool:"GET /headers HTTP/1.1" 200 226
Inactivista
fuente
1
Gracias, @ EmmettJ.Butler =) Aunque no estoy seguro de que esta información estuviera disponible en el momento de la consulta original.
Inactivista
9
Tenga en cuenta que httplib no está disponible en Python 3. Para que el código sea portátil, reemplácelo import httplibcon import requests.packages.urllib3.connectionpool as httplibo use six y from six.moves import http_client as httplib.
Jason R. Coombs
En requests2.18.1 y Python 3, el registrador logging.getLogger("requests.packages.urllib3")no existe o no tiene ningún efecto.
Flimm
1
para Python3 ver aquí - docs.python-requests.org/en/latest/api/?highlight=debug from http.client import HTTPConnection
shershen
Lamentablemente, las líneas "enviar:" "responder:" y "encabezado:" no se registran realmente, sino que simplemente se imprimen en stdout. ¡Pero quiero tener esta información en los archivos de registro!
lesnik
145
r = requests.get('https://api.github.com', auth=('user', 'pass'))

rEs una respuesta. Tiene un atributo de solicitud que tiene la información que necesita.

r.request.allow_redirects  r.request.headers          r.request.register_hook
r.request.auth             r.request.hooks            r.request.response
r.request.cert             r.request.method           r.request.send
r.request.config           r.request.params           r.request.sent
r.request.cookies          r.request.path_url         r.request.session
r.request.data             r.request.prefetch         r.request.timeout
r.request.deregister_hook  r.request.proxies          r.request.url
r.request.files            r.request.redirect         r.request.verify

r.request.headers da los encabezados:

{'Accept': '*/*',
 'Accept-Encoding': 'identity, deflate, compress, gzip',
 'Authorization': u'Basic dXNlcjpwYXNz',
 'User-Agent': 'python-requests/0.12.1'}

Luego r.request.datatiene el cuerpo como un mapeo. Puedes convertir esto con urllib.urlencodesi lo prefieren:

import urllib
b = r.request.data
encoded_body = urllib.urlencode(b)

dependiendo del tipo de respuesta, el .dataatributo puede faltar y en su lugar .bodyhabrá un atributo.

Skylar Saveland
fuente
14
¿Cuál de estos me da "toda la solicitud, encabezados incluidos"?
Chris B.
1
agregó un poco más. ¿Qué más necesitas además de los encabezados y el cuerpo?
Skylar Saveland
8
No estoy completamente seguro de lo que están buscando. Tenía la esperanza de capturar todo lo que pasó por el cable para ellos, en ese formato exacto, byte por byte.
Chris B.
18
Esta es la forma preferida de hacerlo en mi caso. Solo una nota: la response.requestparece ser una PreparedRequesten mi caso; no tiene .datasino en su .bodylugar.
Antti Haapala
2
para la URL completa (con los parámetros de cadena de consulta) también puede usar response.url (que es un poco diferente en que no lo es)response.request...
Chuck van der Linden
7

Puede usar HTTP Toolkit para hacer exactamente esto.

Es especialmente útil si necesita hacer esto rápidamente, sin cambios de código: puede abrir un terminal desde HTTP Toolkit, ejecutar cualquier código de Python desde allí de manera normal, y podrá ver el contenido completo de cada HTTP / HTTPS Solicitar de inmediato.

Hay una versión gratuita que puede hacer todo lo que necesita, y es 100% de código abierto.

Soy el creador de HTTP Toolkit; ¡Realmente lo construí yo mismo para resolver exactamente el mismo problema para mí hace un tiempo! Yo también estaba tratando de depurar una integración de pago, pero su SDK no funcionaba, no podía decir por qué, y necesitaba saber qué estaba pasando para solucionarlo correctamente. Es muy frustrante, pero poder ver el tráfico sin procesar realmente ayuda.

Tim Perry
fuente
5

Si está utilizando Python 2.x, intente instalar un abridor urllib2 . Eso debería imprimir sus encabezados, aunque es posible que tenga que combinar eso con otros abridores que está utilizando para golpear el HTTPS.

import urllib2
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)))
urllib2.urlopen(url)
Kafonek
fuente
2

La verboseopción de configuración puede permitirle ver lo que desea. Hay un ejemplo en la documentación .

NOTA: Lea los comentarios a continuación: Las opciones de configuración detalladas ya no parecen estar disponibles.

Bruno
fuente
3
¿Ahi esta? Realmente no puedo encontrarlo.
BastiBen
3
@gato malo. Había una sección de "Registro detallado" en ese momento . Parece que fue eliminado en diciembre .
Bruno
2
Ah, eso explicaría eso. :) Aún así, ahora esta pregunta es válida nuevamente, porque no pude encontrar una manera de imprimir todo el tráfico entre el servidor y el cliente para la depuración.
BastiBen
1
¿Existe una "nueva forma" recomendada para lograr el mismo efecto que el registro detallado?
cbare
1
Mi respuesta demuestra el método correcto para las solicitudes 1.xy superiores.
Inactivista