Requests ProxyError op 'n private API? Kyk eerste na die omgewing
Requests voeg proxy-, auth- en CA-instellings uit die omgewing saam. Lees wat die proses sien, sluit die private gasheer uit en hou TLS-verifikasie aan.
Die VPN is op, die interne paneelbord open in 'n blaaier, en die Python-skrip gooi steeds 'n proxy-fout. Niks is verkeerd met die tonnel in daardie prentjie nie: die tolk lees 'n proxy-adres uit sy eie omgewing en stuur die versoek daarheen. Hierdie prosedure lees die omgewing wat die proses werklik sien, pas die nouste uitsluiting toe en oorweeg eers daarna 'n eksplisiete sessiebeleid. Elke stap eindig met 'n opdrag waarvan die uitvoer bepaal of jy voortgaan.
Lees die omgewing wat die proses werklik sien
Lessenaar-proxy-instellings, skel-uitvoere en die Environment=-lyne van 'n systemd-eenheid is drie verskillende bronne, en Requests lees net die laaste een wat hy erf. Voer die diagnostiek hieronder uit in dieselfde skel, houer of eenheid wat die foutiewe skrip laat loop, nie in jou interaktiewe terminaal nie. 'n Veranderlike wat in jou aanmeldskel uitgevoer is, is onsigbaar vir 'n houerproses, en daardie gaping verklaar baie verslae van 'n proxy wat uit die niet verskyn. Die twee opdragte druk dieselfde data op verskillende vlakke van detail.
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()]"
Albei spellings van elke veranderlike word gelees, en duplikaat-inskrywings word toegepas in die volgorde waarin die proses hulle ontvang het, so 'n verouderde HTTP_PROXY kan die waarde wat jy pas uitgevoer het, oorheers. Die CA-bundel-veranderlikes maak hier ook saak, want hulle verander waarna verify oplos sonder om enige plek in die kode te verskyn. As die uitvoer leeg is, is die omgewing nie jou probleem nie en kan jy ophou om hierdie afdeling te lees. As dit 'n proxy lys wat jy nie herken nie, vind die lêer of eenheid wat dit stel voordat jy enigiets verander.
Vra Requests wat hy met 'n spesifieke URL sou doen. Hierdie oproep wys die saamgevoegde proxy-, verify- en cert-waardes vir daardie versoek sonder om 'n pakket te stuur.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
'n Nie-leë proxies-inskrywing vir die private gasheer is jou antwoord, en die gedrukte verify-waarde sê watter CA-bundel die versoek sou vertrou. As albei korrek lyk, is die fout later in die stapel en moet jy na die verifikasie-afdeling spring. Moenie uit die kode raai nie: die samesmelting gebeur per versoek, daarom kan een sessie vir twee gashere anders optree.
Sluit die private gasheer uit voordat jy enigiets deaktiveer
Wanneer die proxy werklik vir ander bestemmings nodig is, is die nou regstelling 'n uitsluiting vir hierdie gasheer. Voeg by die bestaande lys toe in plaas van om dit te vervang, want om NO_PROXY uit te wis, breek elke ander interne bestemming wat daarop staatgemaak het. Die opdragte hieronder voeg die inskrywing by en vra dan vir Requests of die omleiding van toepassing is.
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))"
Passing is volgens gasheersuffiks, so .corp.example dek die hele domein terwyl api.corp.example een naam dek. 'n Kaal asterisk deaktiveer proxy vir elke gasheer en is byna nooit wat 'n produksietaak wil hê nie. Of 'n CIDR-inskrywing geëer word, hang af van die Requests- en urllib3-weergawes in die beeld, so toets die presiese inskrywing eerder as om aan te neem dit werk. Kontroleer die resultaat van should_bypass_proxies vir die werklike URL, nie vir 'n gasheernaam wat jy uit die geheue getik het nie.
Hou die twee lae apart in jou kop. Om die HTTP-proxy te omseil, omseil nie die VPN nie, want die proxy-besluit gebeur in die biblioteek en die tonnelbesluit gebeur in die kern se roetetabel.
Deaktiveer trust_env net as 'n doelbewuste sessiebeleid
As die hele taak omgewingskonfigurasie moet ignoreer, bou die sessie eksplisiet en teken die besluit in kode aan. Dit is 'n beleid, nie 'n omweg nie, en dit hoort in 'n diff wat 'n keurder kan sien. Die voorbeeld hieronder hou 'n tydperk, 'n eksplisiete CA-pad en 'n statuskontrole.
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()
Om trust_env af te skakel, verander drie gedragte tegelyk, en net een daarvan gaan oor proxy's. Requests stop om .netrc-geloofsbriewe te lees, en die REQUESTS_CA_BUNDLE- en CURL_CA_BUNDLE-veranderlikes stop om verify te beïnvloed, wat dan terugval op die ingeslote sertifikaatstoor. As jou organisasie TLS met sy eie CA termineer, laat daardie terugval 'n verifikasiefout opduik wat lyk of dit niks met die verandering te doen het nie. Om verify eksplisiet deur te gee, is wat die twee effekte apart hou.
Wat jy nie moet doen nie, is om verify=False te stel om die gevolglike fout stil te maak. Dit ruil 'n proxy-waninstelling vir 'n onverifieerde verbinding, en dit verberg die sertifikaatprobleem wat die uitsluiting moes blootlê.
Verifieer die foutiewe laag en hou 'n terugrol
Drie foute lyk in 'n log dieselfde en het niks gemeen nie: 'n proxy wat die bestemming nie kan bereik nie, gooi ProxyError of gee 502 terug, 'n vertrouensprobleem gooi SSLError, en 'n toepassingsverwerping gee 401 of 403 terug. Herhaal die versoek buite Requests om te sien watter een jy het. Die opdragte hieronder verwyder die proxy, toets die sertifikaatketting en herhaal dan die oproep deur die biblioteek.
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)"
As die curl-oproep slaag en die Python-oproep misluk, is die omgewing steeds die verskil. As albei by die TLS-stadium misluk, was die proxy nooit die probleem nie en is die sertifikaatketting dit. As albei 401 teruggee, het die versoek die toepassing bereik en is die oorblywende werk outentisering. Om aan te teken watter van die drie jy gesien het, spaar die volgende persoon 'n uur.
Terugrol is een reël in enige rigting: verwyder die uitsluiting, of skakel trust_env terug. Stoor die vorige NO_PROXY-waarde voordat jy daarby voeg, en verkies 'n omhulselskrip of 'n eenheidsvlak-Environment=-inskrywing bo 'n uitvoer wat net in jou terminaalgeskiedenis leef. Albei veranderinge is in die prosesomgewing sigbaar, so 'n herbegin laat jou gewoonlik na die ou gedrag terugkeer.
Sluit af deur vier dinge te bevestig: die saamgevoegde instellings vir die private URL wys geen proxy nie, die sertifikaat valideer teen die beoogde CA, die versoek gee die status terug wat jy verwag, en die verandering is op 'n herhaalbare plek vasgelê. 'n Groen skrip met 'n onverklaarde omgewing is 'n regstelling wat op die volgende masjien weer breek. Die opdragte in hierdie prosedure is die wat jy in die kaartjie moet plak.