ProxyError Requests pada API peribadi? Semak persekitaran dahulu
Requests menggabungkan tetapan proksi, auth dan CA daripada persekitaran. Baca apa yang dilihat proses, kecualikan hos peribadi dan biarkan pengesahan TLS dihidupkan.
VPN aktif, papan pemuka dalaman terbuka dalam pelayar, tetapi skrip Python masih membuang ralat proksi. Tiada apa yang salah dengan terowong dalam gambaran itu: jurubahasa membaca alamat proksi daripada persekitarannya sendiri dan menghantar permintaan ke sana. Runbook ini membaca persekitaran yang benar-benar dilihat oleh proses, menggunakan pengecualian paling sempit dan hanya kemudian mempertimbangkan dasar sesi yang jelas. Setiap langkah berakhir dengan arahan yang outputnya menentukan sama ada anda meneruskan.
Baca persekitaran yang benar-benar dilihat oleh proses
Tetapan proksi desktop, eksport shell dan baris Environment= unit systemd ialah tiga sumber berbeza, dan Requests hanya membaca yang terakhir yang diwarisinya. Jalankan diagnostik di bawah dalam shell, kontena atau unit yang sama yang menjalankan skrip yang gagal, bukan dalam terminal interaktif anda. Pemboleh ubah yang dieksport dalam shell log masuk anda tidak kelihatan kepada proses kontena, dan jurang itulah yang menjelaskan banyak laporan tentang proksi yang muncul entah dari mana. Kedua-dua arahan mencetak data yang sama pada tahap perincian berbeza.
env | grep -i -E 'proxy|requests_ca_bundle|curl_ca_bundle'
python3 -c "import os;[print(k,'=',v) for k,v in sorted(os.environ.items()) if 'proxy' in k.lower()]"
Kedua-dua ejaan setiap pemboleh ubah dibaca, dan entri pendua digunakan mengikut urutan proses menerimanya, jadi HTTP_PROXY yang lapuk boleh mengatasi nilai yang baru anda eksport. Pemboleh ubah bundle CA juga penting di sini, kerana ia mengubah apa verify diselesaikan tanpa muncul di mana-mana dalam kod. Jika output kosong, persekitaran bukan masalah anda dan anda boleh berhenti membaca bahagian ini. Jika ia menyenaraikan proksi yang anda tidak kenal, cari fail atau unit yang menetapkannya sebelum mengubah apa-apa.
Tanya Requests apa yang akan dilakukannya dengan URL tertentu. Panggilan ini menunjukkan nilai proksi, verify dan cert yang digabungkan untuk permintaan itu tanpa menghantar paket.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
Entri proxies yang tidak kosong untuk hos peribadi ialah jawapan anda, dan nilai verify yang dicetak memberitahu bundle CA mana yang akan dipercayai oleh permintaan. Jika kedua-duanya kelihatan betul, kegagalan berada lebih jauh dalam timbunan dan anda patut melompat ke bahagian pengesahan. Jangan meneka daripada kod: penggabungan berlaku bagi setiap permintaan, sebab itulah satu sesi boleh berkelakuan berbeza untuk dua hos.
Kecualikan hos peribadi sebelum anda melumpuhkan apa-apa
Apabila proksi benar-benar diperlukan untuk destinasi lain, pembetulan sempit ialah pengecualian untuk hos ini. Tambah pada senarai sedia ada dan bukan menggantikannya, kerana memadam NO_PROXY memecahkan setiap destinasi dalaman lain yang bergantung padanya. Arahan di bawah menambah entri itu dan kemudian bertanya kepada Requests sama ada pintasan itu terpakai.
export NO_PROXY="${NO_PROXY:+$NO_PROXY,}api.corp.example,.corp.example"
python3 -c "import requests;print(requests.utils.should_bypass_proxies('https://api.corp.example/status',None))"
Padanan adalah mengikut akhiran hos, jadi .corp.example meliputi seluruh domain manakala api.corp.example meliputi satu nama. Asterisk kosong melumpuhkan proksi untuk setiap hos dan hampir tidak pernah menjadi apa yang diinginkan oleh kerja pengeluaran. Sama ada entri CIDR dihormati bergantung pada versi Requests dan urllib3 dalam imej, jadi uji entri yang tepat dan bukannya menganggap ia berfungsi. Semak hasil should_bypass_proxies untuk URL sebenar, bukan untuk nama hos yang anda taip daripada ingatan.
Simpan dua lapisan itu berasingan dalam fikiran anda. Memintas proksi HTTP tidak memintas VPN, kerana keputusan proksi berlaku dalam pustaka dan keputusan terowong berlaku dalam jadual penghalaan kernel.
Lumpuhkan trust_env hanya sebagai dasar sesi yang disengajakan
Jika keseluruhan kerja perlu mengabaikan konfigurasi persekitaran, bina sesi secara jelas dan catat keputusan itu dalam kod. Itu dasar, bukan jalan pintas, dan ia tergolong dalam diff yang boleh dilihat oleh penyemak. Contoh di bawah mengekalkan timeout, laluan CA yang jelas dan semakan status.
import requests
with requests.Session() as session:
session.trust_env = False
response = session.get(
"https://api.corp.example/status",
timeout=(5, 20),
verify="/etc/ssl/certs/corp-ca.pem",
)
response.raise_for_status()
Mematikan trust_env mengubah tiga tingkah laku sekali gus, dan hanya satu daripadanya berkaitan proksi. Requests berhenti membaca kelayakan .netrc, dan pemboleh ubah REQUESTS_CA_BUNDLE serta CURL_CA_BUNDLE berhenti mempengaruhi verify, yang kemudian kembali kepada stor sijil terbina. Jika organisasi anda menamatkan TLS dengan CA sendiri, pemulihan itu menimbulkan ralat pengesahan yang kelihatan tidak berkaitan dengan perubahan yang baru anda buat. Menghantar verify secara jelas itulah yang memastikan kedua-dua kesan kekal berasingan.
Apa yang anda tidak patut lakukan ialah menetapkan verify=False untuk mendiamkan ralat yang terhasil. Itu menukar salah konfigurasi proksi dengan sambungan yang tidak disahkan, dan ia menyembunyikan masalah sijil yang sepatutnya didedahkan oleh pengecualian itu.
Sahkan lapisan yang gagal dan simpan rollback
Tiga kegagalan kelihatan sama dalam log dan tidak mempunyai apa-apa persamaan: proksi yang tidak dapat mencapai destinasi membuang ProxyError atau mengembalikan 502, masalah kepercayaan membuang SSLError, dan penolakan aplikasi mengembalikan 401 atau 403. Hasilkan semula permintaan di luar Requests untuk melihat yang mana anda ada. Arahan di bawah membuang proksi, menguji rantaian sijil dan kemudian mengulangi panggilan melalui pustaka.
curl -sv --noproxy '*' https://api.corp.example/status -o /dev/null
openssl s_client -connect api.corp.example:443 -servername api.corp.example </dev/null
python3 -c "import requests;r=requests.get('https://api.corp.example/status',timeout=10);print(r.status_code)"
Jika panggilan curl berjaya dan panggilan Python gagal, persekitaran masih menjadi perbezaannya. Jika kedua-duanya gagal pada peringkat TLS, proksi tidak pernah menjadi masalah dan rantaian sijillah masalahnya. Jika kedua-duanya mengembalikan 401, permintaan telah sampai kepada aplikasi dan kerja yang tinggal ialah pengesahan. Mencatat yang mana antara tiga yang anda perhatikan menjimatkan satu jam orang seterusnya.
Rollback ialah satu baris ke kedua-dua arah: buang pengecualian, atau balikkan trust_env. Simpan nilai NO_PROXY sebelumnya sebelum menambah, dan utamakan skrip pembalut atau entri Environment= peringkat unit berbanding eksport yang hanya hidup dalam sejarah terminal anda. Kedua-dua perubahan kelihatan dalam persekitaran proses, jadi mula semula biasanya mengembalikan anda kepada tingkah laku lama.
Akhiri dengan mengesahkan empat perkara: tetapan gabungan untuk URL peribadi tidak menunjukkan proksi, sijil disahkan terhadap CA yang dimaksudkan, permintaan mengembalikan status yang anda jangkakan, dan perubahan itu komited di tempat yang boleh dihasilkan semula. Skrip hijau dengan persekitaran yang tidak dijelaskan ialah pembetulan yang akan rosak semula pada mesin seterusnya. Arahan dalam runbook ini ialah yang perlu ditampal dalam tiket.