Wie kann ich die gesamte HTTP-Anfrage sehen, die von meiner Python-Anwendung gesendet wird?

263

In meinem Fall verwende ich die requestsBibliothek, um die PayPal-API über HTTPS aufzurufen. Leider erhalte ich einen Fehler von PayPal, und der PayPal-Support kann nicht herausfinden, was der Fehler ist oder was ihn verursacht. Sie möchten, dass ich "Bitte geben Sie die gesamte Anfrage an, einschließlich der Überschriften".

Wie kann ich das machen?

Chris B.
quelle

Antworten:

498

Eine einfache Methode: Aktivieren Sie die Protokollierung in neueren Versionen von Requests (1.x und höher).

Requests verwendet die Konfiguration http.clientund das loggingModul, um die Ausführlichkeit der Protokollierung zu steuern, wie hier beschrieben .

Demonstration

Code aus der verknüpften Dokumentation:

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')

Beispielausgabe

$ 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
Inaktivist
quelle
1
Danke, @ EmmettJ.Butler =) Obwohl ich nicht sicher bin, ob diese Informationen zum Zeitpunkt der ursprünglichen Anfrage verfügbar waren.
Inaktivist
9
Beachten Sie, dass httplib in Python 3 nicht verfügbar ist. Um den Code portabel zu machen, ersetzen Sie ihn import httplibdurch import requests.packages.urllib3.connectionpool as httpliboder verwenden Sie sechs und from six.moves import http_client as httplib.
Jason R. Coombs
In requests2.18.1 und Python 3 ist der Logger logging.getLogger("requests.packages.urllib3")nicht vorhanden oder hat keine Auswirkung.
Flimm
1
Python3 finden Sie hier - docs.python-requests.org/en/latest/api/?highlight=debug from http.client import HTTPConnection
shershen
Leider werden die Zeilen "send:" "reply:" und "header:" nicht protokolliert, sondern nur auf stdout gedruckt. Aber ich möchte diese Informationen in den Protokolldateien haben!
Lesnik
145
r = requests.get('https://api.github.com', auth=('user', 'pass'))

rist eine Antwort. Es verfügt über ein Anforderungsattribut mit den benötigten Informationen.

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 gibt die Überschriften:

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

Dann r.request.datahat der Körper als Mapping. Sie können dies mit konvertierenurllib.urlencode wenn sie bevorzugen:

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

Abhängig von der Art der Antwort .datafehlt möglicherweise das -attribute und .bodystattdessen ist ein -attribute vorhanden.

Skylar Saveland
quelle
14
Welche davon gibt mir "die gesamte Anfrage, einschließlich Header"?
Chris B.
1
fügte noch etwas hinzu. Was brauchen Sie außer den Überschriften und dem Körper noch?
Skylar Saveland
8
Ich bin mir nicht ganz sicher, wonach sie suchen. Ich hatte gehofft, alles, was für sie über den Draht ging, in genau diesem Format Byte für Byte erfassen zu können.
Chris B.
18
Dies ist in meinem Fall die bevorzugte Methode. Nur eine Anmerkung: die response.requestscheint PreparedRequestin meinem Fall eine zu sein; es hat .dataaber .bodystattdessen nicht.
Antti Haapala
2
Für die vollständige URL (mit den Querystring-Parametern) können Sie auch verwenden response.url (was etwas anders ist, da dies nicht der Fall istresponse.request...
Chuck van der Linden
6

Sie können das HTTP Toolkit verwenden , um genau dies zu tun.

Dies ist besonders nützlich, wenn Sie dies schnell und ohne Codeänderungen tun müssen: Sie können ein Terminal über das HTTP-Toolkit öffnen, von dort aus wie gewohnt beliebigen Python-Code ausführen und den vollständigen Inhalt jedes HTTP / HTTPS anzeigen sofort anfordern.

Es gibt eine kostenlose Version, die alles kann, was Sie brauchen, und sie ist 100% Open Source.

Ich bin der Schöpfer des HTTP Toolkit. Ich habe es tatsächlich selbst gebaut, um vor einiger Zeit genau das gleiche Problem für mich zu lösen! Auch ich habe versucht, eine Zahlungsintegration zu debuggen, aber das SDK hat nicht funktioniert, ich konnte nicht sagen warum und ich musste wissen, was tatsächlich vor sich ging, um es richtig zu beheben. Es ist sehr frustrierend, aber es hilft wirklich, den rohen Verkehr zu sehen.

Tim Perry
quelle
5

Wenn Sie Python 2.x verwenden, installieren Sie einen urllib2- Opener. Das sollte Ihre Header ausdrucken, obwohl Sie dies möglicherweise mit anderen Öffnern kombinieren müssen, die Sie verwenden, um das HTTPS zu treffen.

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

Mit der verboseKonfigurationsoption können Sie möglicherweise sehen, was Sie möchten. Es gibt ein Beispiel in der Dokumentation .

HINWEIS: Lesen Sie die folgenden Kommentare: Die ausführlichen Konfigurationsoptionen scheinen nicht mehr verfügbar zu sein.

Bruno
quelle
3
Es gibt? Kann es nicht wirklich finden.
BastiBen
3
@böse Katze. Zu dieser Zeit gab es einen Abschnitt "Ausführliche Protokollierung" . Es scheint, dass es im Dezember entfernt wurde .
Bruno
2
Ah, das würde das erklären. :) Trotzdem ist diese Frage jetzt wieder gültig, da ich keine Möglichkeit gefunden habe, den gesamten Datenverkehr zwischen Server und Client zum Debuggen zu drucken.
BastiBen
1
Gibt es einen empfohlenen "neuen Weg", um den gleichen Effekt wie bei der ausführlichen Protokollierung zu erzielen?
Cbare
1
Meine Antwort zeigt die richtige Methode für Anfragen 1.x und höher.
Inaktivist