Bagaimana saya bisa melihat seluruh permintaan HTTP yang dikirim oleh aplikasi Python saya?

263

Dalam kasus saya, saya menggunakan requestsperpustakaan untuk memanggil API PayPal melalui HTTPS. Sayangnya, saya mendapatkan pesan kesalahan dari PayPal, dan dukungan PayPal tidak dapat menemukan apa kesalahannya atau apa penyebabnya. Mereka ingin saya "Harap berikan seluruh permintaan, termasuk tajuk".

Bagaimana saya bisa melakukan itu?

Chris B.
sumber

Jawaban:

499

Metode sederhana: aktifkan masuk dalam versi terbaru dari Permintaan (1.x dan lebih tinggi.)

Permintaan menggunakan http.clientdan loggingkonfigurasi modul untuk mengontrol verbositas logging, seperti dijelaskan di sini .

Demonstrasi

Kode dikutip dari dokumentasi tertaut:

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

Contoh Output

$ 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
Inactivist
sumber
1
Terima kasih, @ EmmettJ.Butler =) Meskipun saya tidak yakin info ini tersedia pada saat pertanyaan awal.
Inactivist
9
Perhatikan bahwa httplib tidak tersedia di Python 3. Untuk membuat kode portabel, ganti import httplibdengan import requests.packages.urllib3.connectionpool as httplibatau gunakan enam dan from six.moves import http_client as httplib.
Jason R. Coombs
Di requests2.18.1 dan Python 3, logger logging.getLogger("requests.packages.urllib3")tidak ada atau tidak berpengaruh.
Flimm
1
untuk Python3 lihat di sini - docs.python-requests.org/en/latest/api/?highlight=debug from http.client import HTTPConnection
shershen
Sayangnya baris "send:" "reply:" dan "header:" tidak benar-benar dicatat, tetapi hanya dicetak ke stdout. Tapi saya ingin memiliki info ini di file log!
lesnik
145
r = requests.get('https://api.github.com', auth=('user', 'pass'))

radalah tanggapan. Ini memiliki atribut permintaan yang memiliki informasi yang Anda butuhkan.

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 memberi header:

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

Kemudian r.request.datamemiliki tubuh sebagai pemetaan. Anda dapat mengonversi ini dengan urllib.urlencodejika mereka lebih suka:

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

tergantung pada jenis responsnya, .data-atribut mungkin tidak ada dan .body-atribut ada di sana.

Skylar Saveland
sumber
14
Manakah dari ini memberi saya "seluruh permintaan, termasuk header"?
Chris B.
1
menambahkan lagi. Apa lagi yang Anda butuhkan selain header dan tubuh?
Skylar Saveland
8
Saya tidak sepenuhnya yakin apa yang mereka cari. Saya berharap untuk menangkap semua yang melewati kawat untuk mereka, dalam format yang tepat, byte-for-byte.
Chris B.
18
Ini adalah cara yang disukai untuk melakukannya dalam kasus saya. Hanya satu catatan: response.requestsepertinya ada PreparedRequestdalam kasus saya; tidak memiliki .datatetapi .bodysebaliknya.
Antti Haapala
2
untuk URL lengkap (dengan parameter querystring) Anda juga dapat menggunakan response.url (yang sedikit berbeda karena bukanresponse.request...
Chuck van der Linden
7

Anda dapat menggunakan HTTP Toolkit untuk melakukan hal ini.

Ini sangat berguna jika Anda perlu melakukan ini dengan cepat, tanpa perubahan kode: Anda dapat membuka terminal dari HTTP Toolkit, menjalankan kode Python dari sana seperti biasa, dan Anda akan dapat melihat konten lengkap dari setiap HTTP / HTTPS minta segera.

Ada versi gratis yang dapat melakukan semua yang Anda butuhkan, dan 100% open source.

Saya pencipta HTTP Toolkit; Saya benar-benar membangunnya sendiri untuk menyelesaikan masalah yang sama persis untuk saya beberapa waktu lalu! Saya juga mencoba men-debug integrasi pembayaran, tetapi SDK mereka tidak berfungsi, saya tidak tahu mengapa, dan saya perlu tahu apa yang sebenarnya terjadi untuk memperbaikinya dengan benar. Ini sangat membuat frustrasi, tetapi bisa melihat lalu lintas mentah sangat membantu.

Tim Perry
sumber
5

Jika Anda menggunakan Python 2.x, coba instal pembuka urllib2 . Itu akan mencetak header Anda, meskipun Anda mungkin harus menggabungkannya dengan pembuka lain yang Anda gunakan untuk menekan HTTPS.

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

The verbosepilihan konfigurasi mungkin memungkinkan Anda untuk melihat apa yang Anda inginkan. Ada contoh dalam dokumentasi .

CATATAN: Baca komentar di bawah ini: Opsi konfigurasi verbose tampaknya tidak tersedia lagi.

Bruno
sumber
3
Ada? Tidak dapat menemukannya.
BastiBen
3
@kucing nakal. Ada bagian "Verbose Logging" pada saat itu . Tampaknya sudah dihapus pada bulan Desember .
Bruno
2
Ah, itu akan menjelaskan itu. :) Namun, sekarang pertanyaan ini agak valid lagi, karena saya tidak dapat menemukan cara untuk mencetak seluruh lalu lintas antara server dan klien untuk debugging.
BastiBen
1
Apakah ada "cara baru" yang direkomendasikan untuk mencapai efek yang sama dengan logging verbose?
cbare
1
Jawaban saya menunjukkan metode yang benar untuk Permintaan 1.x dan lebih tinggi.
Inactivist