„Requests“ ProxyError privačiame API? Pirmiausia patikrinkite aplinką
„Requests“ sujungia tarpinio serverio, autentifikavimo ir CA nustatymus iš aplinkos. Perskaitykite, ką mato procesas, išskirkite privatų prieglobos serverį ir palikite TLS tikrinimą įjungtą.
VPN veikia, vidinė suvestinė atsidaro naršyklėje, o Python scenarijus vis tiek meta tarpinio serverio klaidą. Šiame vaizde su tuneliu viskas gerai: interpretatorius nuskaito tarpinio serverio adresą iš savo aplinkos ir siunčia užklausą ten. Šis vadovas nuskaito aplinką, kurią procesas iš tikrųjų mato, taiko siauriausią išskyrimą ir tik po to svarsto aiškią sesijos taisyklę. Kiekvienas žingsnis baigiasi komanda, kurios išvestis nusprendžia, ar tęsti.
Perskaitykite aplinką, kurią procesas iš tikrųjų mato
Darbalaukio tarpinio serverio nustatymai, apvalkalo eksportai ir systemd bloko Environment= eilutės yra trys skirtingi šaltiniai, o „Requests“ skaito tik paskutinį, kurį paveldi. Paleiskite žemiau pateiktą diagnostiką tame pačiame apvalkale, konteineryje ar bloke, kuriame veikia nepavykstantis scenarijus, o ne savo interaktyviame terminale. Prisijungimo apvalkale eksportuotas kintamasis konteinerio procesui yra nematomas, ir šis trūkumas paaiškina daugybę pranešimų apie tarpinį serverį, kuris atsiranda iš niekur. Abi komandos spausdina tuos pačius duomenis skirtingu išsamumo lygiu.
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()]"
Skaitomos abi kiekvieno kintamojo rašybos, o pasikartojantys įrašai taikomi ta tvarka, kuria procesas juos gavo, todėl pasenęs HTTP_PROXY gali užgožti ką tik eksportuotą reikšmę. CA paketo kintamieji čia taip pat svarbūs, nes jie keičia, į ką sprendžiasi verify, niekur nepasirodydami kode. Jei išvestis tuščia, aplinka nėra jūsų problema ir galite nustoti skaityti šį skyrių. Jei ji išvardija tarpinį serverį, kurio neatpažįstate, prieš ką nors keisdami raskite failą ar bloką, kuris jį nustato.
Paklauskite „Requests“, ką jis darytų su konkrečiu URL. Šis kvietimas parodo sujungtas tos užklausos tarpinio serverio, verify ir cert reikšmes nesiunčiant paketo.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
Netuščias proxies įrašas privačiam prieglobos serveriui yra jūsų atsakymas, o atspausdinta verify reikšmė pasako, kuriuo CA paketu užklausa pasitikėtų. Jei abu atrodo teisingi, gedimas yra toliau kamino viršuje ir turėtumėte pereiti prie tikrinimo skyriaus. Nespėliokite iš kodo: sujungimas atliekamas kiekvienai užklausai, todėl viena sesija gali elgtis skirtingai su dviem prieglobos serveriais.
Išskirkite privatų prieglobos serverį prieš ką nors išjungdami
Kai tarpinis serveris tikrai reikalingas kitiems tikslams, siauras sprendimas yra šio prieglobos serverio išskyrimas. Pridėkite prie esamo sąrašo, o ne pakeiskite jį, nes NO_PROXY ištrynimas sugriaus kiekvieną kitą vidinį tikslą, kuris juo rėmėsi. Toliau pateiktos komandos prideda įrašą ir tada klausia „Requests“, ar apėjimas galioja.
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))"
Suderinimas vyksta pagal prieglobos serverio galūnę, todėl .corp.example apima visą domeną, o api.corp.example – vieną vardą. Vien žvaigždutė išjungia tarpinį serverį visiems prieglobos serveriams ir beveik niekada nėra tai, ko nori gamybinė užduotis. Ar CIDR įrašas bus paisomas, priklauso nuo „Requests“ ir urllib3 versijų atvaizde, todėl išbandykite tikslų įrašą, o ne manykite, kad jis veikia. Patikrinkite should_bypass_proxies rezultatą tikram URL, o ne prieglobos serverio vardui, kurį įvedėte iš atminties.
Laikykite du sluoksnius atskirai galvoje. HTTP tarpinio serverio apėjimas neapeina VPN, nes sprendimas dėl tarpinio serverio priimamas bibliotekoje, o sprendimas dėl tunelio – branduolio maršrutizavimo lentelėje.
Išjunkite trust_env tik kaip sąmoningą sesijos taisyklę
Jei visas darbas turi ignoruoti aplinkos konfigūraciją, sukurkite sesiją aiškiai ir užfiksuokite sprendimą kode. Tai taisyklė, o ne apeinamasis sprendimas, ir ji priklauso diff, kurį mato recenzentas. Toliau pateiktas pavyzdys išlaiko skirtąjį laiką, aiškų CA kelią ir būsenos patikrinimą.
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()
Išjungus trust_env iš karto pasikeičia trys elgsenos, ir tik viena jų susijusi su tarpiniu serveriu. „Requests“ nustoja skaityti .netrc kredencialus, o kintamieji REQUESTS_CA_BUNDLE ir CURL_CA_BUNDLE nustoja paveikti verify, kuris tada grįžta prie įtrauktos sertifikatų saugyklos. Jei jūsų organizacija užbaigia TLS savo CA, tas grįžimas sukelia tikrinimo klaidą, kuri atrodo nesusijusi su ką tik atliktu pakeitimu. Būtent aiškus verify perdavimas išlaiko du poveikius atskirai.
Ko neturėtumėte daryti, tai nustatyti verify=False, kad nutildytumėte atsiradusią klaidą. Taip tarpinio serverio konfigūracijos klaida pakeičiama nepatikrintu ryšiu, ir paslepiama sertifikato problema, kurią išskyrimas turėjo atskleisti.
Patikrinkite nepavykusį sluoksnį ir išsaugokite galimybę atšaukti
Trys gedimai žurnale atrodo vienodai ir neturi nieko bendra: tarpinis serveris, kuris nepasiekia tikslo, meta ProxyError arba grąžina 502, pasitikėjimo problema meta SSLError, o programos atmetimas grąžina 401 arba 403. Atkurkite užklausą už „Requests“ ribų, kad pamatytumėte, kuris iš jų yra jūsų. Toliau pateiktos komandos pašalina tarpinį serverį, išbando sertifikatų grandinę ir tada pakartoja kvietimą per biblioteką.
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)"
Jei curl kvietimas pavyksta, o Python kvietimas nepavyksta, skirtumas vis dar yra aplinka. Jei abu nepavyksta TLS etape, tarpinis serveris niekada nebuvo problema, o problema yra sertifikatų grandinė. Jei abu grąžina 401, užklausa pasiekė programą, o likęs darbas yra autentifikavimas. Užrašymas, kurį iš trijų pastebėjote, sutaupo kitam žmogui valandą.
Atšaukimas yra viena eilutė abiem kryptimis: pašalinkite išskyrimą arba grąžinkite trust_env atgal. Išsaugokite ankstesnę NO_PROXY reikšmę prieš ką nors pridėdami, ir pirmenybę teikite apvalkalo scenarijui arba bloko lygio Environment= įrašui, o ne eksportui, kuris gyvena tik jūsų terminalo istorijoje. Abu pakeitimai matomi proceso aplinkoje, todėl perkrovimas paprastai grąžina jus prie senos elgsenos.
Užbaikite patvirtindami keturis dalykus: sujungti privataus URL nustatymai nerodo jokio tarpinio serverio, sertifikatas patvirtinamas pagal numatytą CA, užklausa grąžina laukiamą būseną, o pakeitimas įrašytas ten, kur jį galima atkurti. Žalias scenarijus su nepaaiškinta aplinka yra pataisa, kuri vėl suges kitame kompiuteryje. Šio vadovo komandos yra tos, kurias reikia įklijuoti į bilietą.