Özel bir API'de Requests ProxyError mı? Önce ortamı denetleyin
Requests proxy, kimlik doğrulama ve CA ayarlarını ortamdan birleştirir. Sürecin ne gördüğünü okuyun, özel ana makineyi hariç tutun ve TLS doğrulamasını açık tutun.
VPN açık, iç kontrol paneli tarayıcıda açılıyor ve Python betiği hâlâ proxy hatası veriyor. Bu görüntüde tünelde yanlış bir şey yok: yorumlayıcı kendi ortamından bir proxy adresi okuyor ve isteği oraya gönderiyor. Bu çalışma kılavuzu, sürecin gerçekte gördüğü ortamı okur, en dar dışlamayı uygular ve ancak ondan sonra açık bir oturum ilkesini değerlendirir. Her adım, çıktısı devam edip etmeyeceğinizi belirleyen bir komutla biter.
Sürecin gerçekte gördüğü ortamı okuyun
Masaüstü proxy ayarları, kabuk dışa aktarımları ve bir systemd biriminin Environment= satırları üç ayrı kaynaktır ve Requests yalnızca devraldığı sonuncusunu okur. Aşağıdaki tanılamayı, başarısız betiği çalıştıran aynı kabukta, kapsayıcıda veya birimde çalıştırın; kendi etkileşimli terminalinizde değil. Oturum açma kabuğunuzda dışa aktarılan bir değişken, kapsayıcı süreci için görünmezdir ve bu boşluk, birdenbire ortaya çıkan bir proxy hakkındaki birçok bildirimi açıklar. İki komut aynı verileri farklı ayrıntı düzeylerinde yazdırır.
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()]"
Her değişkenin iki yazımı da okunur ve yinelenen girdiler sürecin onları aldığı sırayla uygulanır, bu yüzden eski bir HTTP_PROXY yeni dışa aktardığınız değeri geçersiz kılabilir. CA paketi değişkenleri burada da önemlidir, çünkü verify değerinin neye çözüleceğini kodda hiç görünmeden değiştirirler. Çıktı boşsa ortam sizin sorununuz değildir ve bu bölümü okumayı bırakabilirsiniz. Tanımadığınız bir proxy listeliyorsa, bir şeyi değiştirmeden önce onu ayarlayan dosyayı veya birimi bulun.
Requests'e belirli bir URL ile ne yapacağını sorun. Bu çağrı, bir paket göndermeden o istek için birleştirilmiş proxy, verify ve cert değerlerini gösterir.
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
Özel ana makine için boş olmayan proxies girdisi sizin yanıtınızdır ve yazdırılan verify değeri isteğin hangi CA paketine güveneceğini söyler. İkisi de doğru görünüyorsa arıza yığında daha ileridedir ve doğrulama bölümüne geçmelisiniz. Koddan tahmin etmeyin: birleştirme her istek için gerçekleşir, bu yüzden bir oturum iki ana makine için farklı davranabilir.
Herhangi bir şeyi devre dışı bırakmadan önce özel ana makineyi hariç tutun
Proxy başka hedefler için gerçekten gerektiğinde, dar düzeltme bu ana makine için bir dışlamadır. Var olan listeye ekleyin, onu değiştirmeyin, çünkü NO_PROXY silmek ona güvenen diğer tüm iç hedefleri bozar. Aşağıdaki komutlar girdiyi ekler ve ardından Requests'e atlamanın geçerli olup olmadığını sorar.
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))"
Eşleşme ana makine son ekine göredir, bu yüzden .corp.example tüm alan adını kapsarken api.corp.example tek bir adı kapsar. Çıplak yıldız her ana makine için proxy'yi devre dışı bırakır ve bir üretim işinin istediği şey neredeyse hiçbir zaman bu değildir. Bir CIDR girdisinin dikkate alınıp alınmayacağı imgedeki Requests ve urllib3 sürümlerine bağlıdır, bu yüzden çalıştığını varsaymak yerine tam girdiyi test edin. should_bypass_proxies sonucunu gerçek URL için denetleyin, bellekten yazdığınız ana makine adı için değil.
İki katmanı kafanızda ayrı tutun. HTTP proxy'sini atlamak VPN'i atlamaz, çünkü proxy kararı kitaplıkta, tünel kararı çekirdeğin yönlendirme tablosunda verilir.
trust_env'yi yalnızca bilinçli bir oturum ilkesi olarak devre dışı bırakın
Tüm iş ortam yapılandırmasını yok sayacaksa, oturumu açıkça kurun ve kararı kodda kaydedin. Bu bir ilkedir, geçici çözüm değildir ve bir incelemecinin görebileceği diff'e aittir. Aşağıdaki örnek zaman aşımını, açık CA yolunu ve durum denetimini korur.
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()
trust_env'ü kapatmak aynı anda üç davranışı değiştirir ve bunlardan yalnızca biri proxy ile ilgilidir. Requests .netrc kimlik bilgilerini okumayı bırakır ve REQUESTS_CA_BUNDLE ile CURL_CA_BUNDLE değişkenleri verify üzerinde etkili olmayı bırakır; o da sonra birlikte gelen sertifika deposuna geri döner. Kuruluşunuz TLS'i kendi CA'sı ile sonlandırıyorsa, bu geri dönüş, az önce yaptığınız değişiklikle ilgisiz görünen bir doğrulama hatası üretir. verify'in açıkça geçirilmesi iki etkiyi ayrı tutan şeydir.
Yapmamanız gereken şey, ortaya çıkan hatayı susturmak için verify=False ayarlamaktır. Bu, yanlış bir proxy yapılandırmasını doğrulanmamış bir bağlantıyla değiştirir ve dışlamanın ortaya çıkarması gereken sertifika sorununu gizler.
Başarısız olan katmanı doğrulayın ve geri alma yolunu koruyun
Üç arıza günlükte aynı görünür ve hiçbir ortak yanı yoktur: hedefe ulaşamayan proxy ProxyError fırlatır veya 502 döndürür, güven sorunu SSLError fırlatır ve uygulama reddi 401 veya 403 döndürür. Hangi durumda olduğunuzu görmek için isteği Requests dışında yeniden üretin. Aşağıdaki komutlar proxy'yi kaldırır, sertifika zincirini test eder ve ardından çağrıyı kitaplık üzerinden tekrarlar.
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)"
curl çağrısı başarılı olup Python çağrısı başarısız olursa, fark hâlâ ortamdır. İkisi de TLS aşamasında başarısız olursa proxy hiçbir zaman sorun olmamıştır ve sorun sertifika zinciridir. İkisi de 401 döndürürse istek uygulamaya ulaşmıştır ve kalan iş kimlik doğrulamadır. Üçünden hangisini gözlemlediğinizi not etmek bir sonraki kişiye bir saat kazandırır.
Geri alma her iki yönde tek satırdır: dışlamayı kaldırın veya trust_env'i geri alın. Bir şey eklemeden önce önceki NO_PROXY değerini kaydedin ve terminal geçmişinizde yaşayan bir dışa aktarım yerine bir sarmalayıcı betiği veya birim düzeyinde Environment= girdisini tercih edin. Her iki değişiklik de süreç ortamında görünür, bu yüzden yeniden başlatma genellikle sizi eski davranışa geri getirir.
Dört şeyi doğrulayarak bitirin: özel URL için birleştirilmiş ayarlar hiçbir proxy göstermiyor, sertifika amaçlanan CA'ya karşı doğrulanıyor, istek beklediğiniz durumu döndürüyor ve değişiklik yeniden üretilebilir bir yerde işlendi. Açıklanamayan bir ortamla yeşil bir betik, bir sonraki makinede yeniden bozulacak bir düzeltmedir. Bu kılavuzdaki komutlar bilete yapıştırılacak olanlardır.