ProxyError a Requestsben egy privát API-nál? Először a környezetet ellenőrizze
A Requests a környezetből egyesíti a proxy-, hitelesítési és CA-beállításokat. Nézze meg, mit lát a folyamat, zárja ki a privát gazdagépet, és tartsa bekapcsolva a TLS-ellenőrzést.
A VPN fut, a belső irányítópult megnyílik a böngészőben, és a Python-szkript továbbra is proxyhibát dob. Ezen a képen semmi baj nincs az alagúttal: az értelmező saját környezetéből olvas egy proxycímet, és oda küldi a kérést. Ez az útmutató azt a környezetet olvassa, amelyet a folyamat valóban lát, a legszűkebb kizárást alkalmazza, és csak ezután vesz fontolóra kifejezett munkamenet-szabályt. Minden lépés egy olyan paranccsal végződik, amelynek kimenete eldönti, hogy folytatja-e.
Olvassa el a környezetet, amelyet a folyamat valóban lát
Az asztali proxybeállítások, a shell-exportok és egy systemd-egység Environment= sorai három különböző forrás, és a Requests csak az utolsót olvassa, amelyet örököl. Futtassa az alábbi diagnosztikát ugyanabban a shellben, konténerben vagy egységben, amely a hibás szkriptet futtatja, ne az interaktív termináljában. A bejelentkezési shelljében exportált változó láthatatlan a konténerfolyamat számára, és ez a rés magyarázza a semmiből megjelenő proxyról szóló sok jelentést. A két parancs ugyanazokat az adatokat különböző részletességgel nyomtatja.
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()]"
Minden változó mindkét írásmódja olvasódik, és az ismétlődő bejegyzések abban a sorrendben érvényesülnek, ahogy a folyamat megkapta őket, így egy elavult HTTP_PROXY felülírhatja az imént exportált értéket. A CA-köteg változói itt is számítanak, mert megváltoztatják, mivé oldódik fel a verify, anélkül hogy bárhol megjelennének a kódban. Ha a kimenet üres, a környezet nem az Ön problémája, és abbahagyhatja e szakasz olvasását. Ha olyan proxyt sorol fel, amelyet nem ismer, keresse meg a beállító fájlt vagy egységet, mielőtt bármit módosítana.
Kérdezze meg a Requestst, mit tenne egy adott URL-lel. Ez a hívás a kérés egyesített proxy-, verify- és cert-értékeit mutatja meg csomag küldése nélkül.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
A privát gazdagéphez tartozó nem üres proxies bejegyzés a válasz, és a kinyomtatott verify érték megmondja, melyik CA-kötegben bízna a kérés. Ha mindkettő helyesnek tűnik, a hiba később van a veremben, és tovább kell lépnie az ellenőrzési szakaszra. Ne találgasson a kódból: az egyesítés kérésenként történik, ezért egy munkamenet két gazdagépnél eltérően viselkedhet.
Zárja ki a privát gazdagépet, mielőtt bármit letiltana
Amikor a proxy valóban szükséges más célokhoz, a szűk javítás ennek a gazdagépnek a kizárása. A meglévő listához fűzze hozzá, ne cserélje le, mert a NO_PROXY törlése minden más belső célt elront, amely rá támaszkodott. Az alábbi parancsok hozzáfűzik a bejegyzést, majd megkérdezik a Requestst, hogy érvényes-e a megkerülés.
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))"
Az egyeztetés gazdagép-utótag szerint történik, így a .corp.example az egész tartományt lefedi, míg a api.corp.example egy nevet fed le. Egy csupasz csillag minden gazdagépnél letiltja a proxyt, és szinte soha nem az, amit egy termelési feladat szeretne. Az, hogy egy CIDR-bejegyzést figyelembe vesznek-e, a képen lévő Requests- és urllib3-verzióktól függ, ezért tesztelje a pontos bejegyzést, ahelyett hogy feltételezné, hogy működik. Ellenőrizze a should_bypass_proxies eredményét a valódi URL-re, ne egy emlékezetből beírt gazdagépnévre.
Tartsa a két réteget külön a fejében. A HTTP-proxy megkerülése nem kerüli meg a VPN-t, mert a proxy döntése a könyvtárban, az alagút döntése pedig a kernel útválasztási táblázatában születik.
A trust_env-t csak szándékos munkamenet-szabályként tiltsa le
Ha az egész feladatnak figyelmen kívül kell hagynia a környezeti konfigurációt, építse fel a munkamenetet kifejezetten, és rögzítse a döntést a kódban. Ez szabály, nem kerülőút, és olyan diffbe való, amelyet a bíráló láthat. Az alábbi példa megtartja az időkorlátot, a kifejezett CA-útvonalat és az állapotellenőrzést.
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()
A trust_env kikapcsolása egyszerre három viselkedést változtat meg, és csak az egyikük szól a proxyról. A Requests abbahagyja a .netrc hitelesítő adatok olvasását, és a REQUESTS_CA_BUNDLE és CURL_CA_BUNDLE változók már nem hatnak a verify-re, amely ilyenkor a beépített tanúsítványtárra esik vissza. Ha a szervezete saját CA-val zárja le a TLS-t, ez a visszaesés olyan ellenőrzési hibát okoz, amely az imént tett változtatástól függetlennek tűnik. A verify kifejezett átadása az, ami a két hatást külön tartja.
Amit nem szabad tennie, az az, hogy a keletkező hiba elnémítására verify=False-et állít be. Ez egy rossz proxykonfigurációt cserél ellenőrizetlen kapcsolatra, és elrejti azt a tanúsítványproblémát, amelyet a kizárásnak fel kellett volna tárnia.
Ellenőrizze a hibás réteget, és tartson fenn visszaállítási lehetőséget
Három hiba hasonlóan néz ki egy naplóban, és semmi közös nincs bennük: a célt el nem érő proxy ProxyError-et dob vagy 502-t ad vissza, a bizalmi probléma SSLError-et dob, az alkalmazás elutasítása pedig 401-et vagy 403-at ad vissza. Reprodukálja a kérést a Requestsen kívül, hogy lássa, melyik van Önnél. Az alábbi parancsok eltávolítják a proxyt, tesztelik a tanúsítványláncot, majd megismétlik a hívást a könyvtáron keresztül.
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)"
Ha a curl-hívás sikerül és a Python-hívás meghiúsul, a különbség továbbra is a környezet. Ha mindkettő a TLS szakaszban hiúsul meg, a proxy soha nem volt a probléma, és a tanúsítványlánc az. Ha mindkettő 401-et ad vissza, a kérés elérte az alkalmazást, és a hátralévő munka a hitelesítés. Annak rögzítése, melyiket látta a háromból, egy órát spórol a következő embernek.
A visszaállítás egy sor mindkét irányban: távolítsa el a kizárást, vagy fordítsa vissza a trust_env-et. Mentse el az előző NO_PROXY értéket, mielőtt hozzáfűzne, és részesítse előnyben a burkolószkriptet vagy az egységszintű Environment= bejegyzést a csak a terminálja előzményeiben élő exporthoz képest. Mindkét változás látható a folyamat környezetében, így az újraindítás általában visszahozza a régi viselkedést.
Fejezze be négy dolog megerősítésével: a privát URL egyesített beállításai nem mutatnak proxyt, a tanúsítvány a tervezett CA-val szemben érvényesül, a kérés a várt állapotot adja vissza, és a változás reprodukálható helyen van commitolva. Egy zöld szkript megmagyarázatlan környezettel olyan javítás, amely a következő gépen újra elromlik. Az útmutató parancsai azok, amelyeket a jegybe kell beilleszteni.