ProxyError i Requests mot en privat API? Sjekk miljøet først
Requests slår sammen proxy-, auth- og CA-innstillinger fra miljøet. Les hva prosessen ser, utelukk den private verten og la TLS-verifiseringen stå på.
VPN er oppe, det interne dashbordet åpnes i en nettleser, og Python-skriptet kaster fortsatt en proxyfeil. Det er ingenting galt med tunnelen i det bildet: tolkeren leser en proxyadresse fra sitt eget miljø og sender forespørselen dit. Denne runboken leser miljøet prosessen faktisk ser, bruker den smaleste utelukkelsen og vurderer først deretter en eksplisitt sesjonspolicy. Hvert steg ender med en kommando der utdata avgjør om du fortsetter.
Les miljøet prosessen faktisk ser
Proxyinnstillinger på skrivebordet, shell-eksporter og Environment=-linjene i en systemd-enhet er tre forskjellige kilder, og Requests leser bare den siste den arver. Kjør diagnosen nedenfor i samme shell, container eller enhet som kjører skriptet som feiler, ikke i din interaktive terminal. En variabel som er eksportert i innloggingsskjellen din, er usynlig for en containerprosess, og det gapet forklarer mange rapporter om en proxy som dukker opp fra ingenting. De to kommandoene skriver ut de samme dataene på ulike detaljnivåer.
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()]"
Begge skrivemåtene for hver variabel leses, og dupliserte oppføringer brukes i den rekkefølgen prosessen mottok dem, så en utdatert HTTP_PROXY kan overstyre verdien du nettopp eksporterte. CA-bundle-variablene betyr noe her også, fordi de endrer hva verify løses til uten å vises noe sted i koden. Hvis utdataene er tomme, er ikke miljøet problemet ditt, og du kan slutte å lese dette avsnittet. Hvis det viser en proxy du ikke kjenner igjen, finn filen eller enheten som setter den før du endrer noe.
Spør Requests hva den ville gjort med en bestemt URL. Dette kallet viser de sammenslåtte proxy-, verify- og cert-verdiene for den forespørselen uten å sende en pakke.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
En ikke-tom proxies-oppføring for den private verten er svaret ditt, og den utskrevne verify-verdien forteller hvilken CA-bundle forespørselen ville stole på. Hvis begge ser riktige ut, er feilen lenger ned i stakken, og du bør hoppe til verifiseringsavsnittet. Ikke gjett fra koden: sammenslåingen skjer per forespørsel, og derfor kan én sesjon oppføre seg ulikt for to verter.
Utelukk den private verten før du deaktiverer noe
Når proxyen virkelig er nødvendig for andre destinasjoner, er den smale rettelsen en utelukkelse for denne verten. Legg til i den eksisterende listen i stedet for å erstatte den, fordi sletting av NO_PROXY ødelegger enhver annen intern destinasjon som stolte på den. Kommandoene nedenfor legger til oppføringen og spør deretter Requests om omveien gjelder.
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))"
Samsvaret er etter vertssuffiks, så .corp.example dekker hele domenet mens api.corp.example dekker ett navn. En bar stjerne deaktiverer proxy for hver vert og er nesten aldri det en produksjonsjobb vil ha. Om en CIDR-oppføring respekteres, avhenger av Requests- og urllib3-versjonene i imaget, så test den nøyaktige oppføringen i stedet for å anta at den virker. Kontroller resultatet av should_bypass_proxies for den ekte URL-en, ikke for et vertsnavn du skrev fra hukommelsen.
Hold de to lagene adskilt i hodet. Å omgå HTTP-proxyen omgår ikke VPN-en, fordi proxybeslutningen tas i biblioteket og tunnelbeslutningen i kjernens rutetabell.
Deaktiver trust_env bare som en bevisst sesjonspolicy
Hvis hele jobben skal ignorere den omkringliggende konfigurasjonen, bygg sesjonen eksplisitt og registrer beslutningen i koden. Det er en policy, ikke en omvei, og den hører hjemme i en diff en anmelder kan se. Eksempelet nedenfor beholder en timeout, en eksplisitt CA-sti og en statussjekk.
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()
Å slå av trust_env endrer tre atferder på én gang, og bare én av dem handler om proxy. Requests slutter å lese .netrc-legitimasjon, og variablene REQUESTS_CA_BUNDLE og CURL_CA_BUNDLE slutter å påvirke verify, som da faller tilbake til det medfølgende sertifikatlageret. Hvis organisasjonen din avslutter TLS med sin egen CA, gir denne tilbakefallingen en verifiseringsfeil som ser ut til å ikke ha noe med endringen du nettopp gjorde å gjøre. Det er den eksplisitte videreføringen av verify som holder de to effektene adskilt.
Det du ikke bør gjøre, er å sette verify=False for å dempe feilen som oppstår. Det bytter en feilkonfigurert proxy mot en uverifisert tilkobling, og det skjuler sertifikatproblemet som utelukkelsen skulle avdekke.
Verifiser laget som feiler, og behold en tilbakerulling
Tre feil ser like ut i en logg og har ingenting til felles: en proxy som ikke når destinasjonen, kaster ProxyError eller returnerer 502, et tillitsproblem kaster SSLError, og en applikasjonsavvisning returnerer 401 eller 403. Gjenskap forespørselen utenfor Requests for å se hvilken du har. Kommandoene nedenfor fjerner proxyen, tester sertifikatkjeden og gjentar deretter kallet gjennom biblioteket.
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)"
Hvis curl-kallet lykkes og Python-kallet feiler, er miljøet fortsatt forskjellen. Hvis begge feiler i TLS-fasen, var proxyen aldri problemet, og sertifikatkjeden er det. Hvis begge returnerer 401, nådde forespørselen applikasjonen, og det som gjenstår er autentisering. Å notere hvilken av de tre du observerte, sparer neste person en time.
Tilbakerulling er én linje i begge retninger: fjern utelukkelsen, eller snu trust_env tilbake. Lagre den forrige NO_PROXY-verdien før du legger til noe, og foretrekk et wrapper-skript eller en Environment=-oppføring på enhetsnivå fremfor en eksport som bare lever i terminalhistorikken din. Begge endringene er synlige i prosessmiljøet, så en omstart bringer deg vanligvis tilbake til den gamle atferden.
Avslutt med å bekrefte fire ting: de sammenslåtte innstillingene for den private URL-en viser ingen proxy, sertifikatet valideres mot den tiltenkte CA-en, forespørselen returnerer statusen du forventer, og endringen er committet et sted som kan gjenskapes. Et grønt skript med et uforklart miljø er en rettelse som går i stykker igjen på neste maskin. Kommandoene i denne runboken er de du skal lime inn i billetten.