ব্যক্তিগত API-তে Requests ProxyError? আগে পরিবেশ দেখুন
Requests পরিবেশ থেকে প্রক্সি, auth ও CA সেটিংস একত্র করে। প্রসেস যা দেখে তা পড়ুন, ব্যক্তিগত হোস্ট বাদ দিন এবং TLS যাচাই চালু রাখুন।
VPN চালু, অভ্যন্তরীণ ড্যাশবোর্ড ব্রাউজারে খোলে, তবুও Python স্ক্রিপ্টটি প্রক্সি ত্রুটি দেয়। সেই ছবিতে টানেলে কোনো সমস্যা নেই: ইন্টারপ্রেটার নিজের পরিবেশ থেকে প্রক্সি ঠিকানা পড়ে অনুরোধটি সেখানে পাঠাচ্ছে। এই রানবুকে প্রসেসটি আসলে যে পরিবেশ দেখে তা পড়া হয়, সংকীর্ণতম বাদ দেওয়া প্রয়োগ করা হয়, তারপরই স্পষ্ট সেশন নীতি বিবেচনা করা হয়। প্রতিটি ধাপ এমন একটি কমান্ডে শেষ হয় যার আউটপুট আপনি এগোবেন কি না তা ঠিক করে।
প্রসেসটি আসলে যে পরিবেশ দেখে তা পড়ুন
ডেস্কটপ প্রক্সি সেটিংস, shell এক্সপোর্ট এবং একটি systemd ইউনিটের Environment= লাইন — এই তিনটি আলাদা উৎস, আর Requests শুধু উত্তরাধিকারে পাওয়া শেষটিই পড়ে। নিচের ডায়াগনস্টিকটি ব্যর্থ স্ক্রিপ্ট চালানো একই shell, কনটেইনার বা ইউনিটে চালান, আপনার ইন্টারঅ্যাকটিভ টার্মিনালে নয়। আপনার লগইন shell-এ এক্সপোর্ট করা ভেরিয়েবল কনটেইনার প্রসেসের কাছে অদৃশ্য, আর এই ফাঁকই কোথাও থেকে হঠাৎ দেখা দেওয়া প্রক্সির অনেক রিপোর্ট ব্যাখ্যা করে। দুটি কমান্ড একই ডেটা ভিন্ন বিস্তারিত স্তরে ছাপে।
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()]"
প্রতিটি ভেরিয়েবলের দুই বানানই পড়া হয়, আর ডুপ্লিকেট এন্ট্রি প্রসেস যেভাবে পেয়েছে সেই ক্রমে প্রয়োগ হয়, তাই পুরোনো HTTP_PROXY আপনি এইমাত্র এক্সপোর্ট করা মানটিকে ছাপিয়ে যেতে পারে। CA-bundle ভেরিয়েবলগুলোও এখানে গুরুত্বপূর্ণ, কারণ কোডে কোথাও না দেখিয়েও তারা বদলে দেয় verify কীসে রিজলভ হয়। আউটপুট খালি হলে পরিবেশ আপনার সমস্যা নয় এবং এই অংশ পড়া বন্ধ করতে পারেন। যদি এমন প্রক্সি তালিকাভুক্ত হয় যা আপনি চেনেন না, কিছু বদলানোর আগে যে ফাইল বা ইউনিট এটি সেট করে তা খুঁজে বের করুন।
একটি নির্দিষ্ট URL-এ Requests কী করবে তা জিজ্ঞাসা করুন। এই কল কোনো প্যাকেট না পাঠিয়েই সেই অনুরোধের জন্য একত্রিত প্রক্সি, verify ও cert মান দেখায়।
python3 -c "import requests;s=requests.Session();print(s.merge_environment_settings('https://api.corp.example/status',{},None,None,None))"
ব্যক্তিগত হোস্টের জন্য অখালি proxies এন্ট্রিই আপনার উত্তর, আর ছাপা verify মান বলে দেয় অনুরোধটি কোন CA bundle-কে বিশ্বাস করবে। দুটোই ঠিক দেখালে ব্যর্থতা স্ট্যাকের পরের অংশে এবং আপনার যাচাই অংশে যাওয়া উচিত। কোড থেকে আন্দাজ করবেন না: একত্রীকরণ প্রতিটি অনুরোধে ঘটে, তাই একটি সেশন দুটি হোস্টের জন্য ভিন্ন আচরণ করতে পারে।
কিছু নিষ্ক্রিয় করার আগে ব্যক্তিগত হোস্ট বাদ দিন
প্রক্সি সত্যিই অন্য গন্তব্যের জন্য দরকার হলে সংকীর্ণ সমাধান এই হোস্টের জন্য বাদ দেওয়া। বিদ্যমান তালিকায় যোগ করুন, প্রতিস্থাপন করবেন না, কারণ NO_PROXY মুছে ফেললে এর উপর নির্ভর করা অন্য সব অভ্যন্তরীণ গন্তব্য ভেঙে যায়। নিচের কমান্ডগুলো এন্ট্রি যোগ করে, তারপর Requests-কে জিজ্ঞাসা করে বাইপাস প্রযোজ্য কি না।
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))"
মিল হয় হোস্ট সাফিক্স অনুযায়ী, তাই .corp.example পুরো ডোমেইন জুড়ে আর api.corp.example একটি নাম জুড়ে। খালি অ্যাস্টেরিস্ক প্রতিটি হোস্টের জন্য প্রক্সি বন্ধ করে এবং প্রোডাকশন কাজ প্রায় কখনোই তা চায় না। CIDR এন্ট্রি মানা হবে কি না তা ইমেজের Requests ও urllib3 সংস্করণের উপর নির্ভর করে, তাই কাজ করবে ধরে না নিয়ে ঠিক এন্ট্রিটিই পরীক্ষা করুন। should_bypass_proxies-এর ফলাফল সত্যিকারের URL-এর জন্য দেখুন, স্মৃতি থেকে টাইপ করা হোস্টনামের জন্য নয়।
দুটি স্তরকে মাথায় আলাদা রাখুন। HTTP প্রক্সি বাইপাস করলে VPN বাইপাস হয় না, কারণ প্রক্সির সিদ্ধান্ত নেয় লাইব্রেরি আর টানেলের সিদ্ধান্ত নেয় কার্নেলের রাউটিং টেবিল।
trust_env কেবল সচেতন সেশন নীতি হিসেবেই বন্ধ করুন
পুরো কাজটিকে আশপাশের কনফিগারেশন উপেক্ষা করতে হলে সেশনটি স্পষ্টভাবে গড়ুন এবং সিদ্ধান্ত কোডে লিখুন। এটি একটি নীতি, কোনো কাজের চারপাশে ঘোরার উপায় নয়, এবং এটি এমন diff-এ থাকা উচিত যা রিভিউয়ার দেখতে পান। নিচের উদাহরণে টাইমআউট, স্পষ্ট CA পাথ ও স্ট্যাটাস চেক রাখা হয়েছে।
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 বন্ধ করলে একসাথে তিনটি আচরণ বদলায়, আর তাদের একটিই প্রক্সি সম্পর্কিত। Requests আর .netrc ক্রেডেনশিয়াল পড়ে না, এবং REQUESTS_CA_BUNDLE ও CURL_CA_BUNDLE ভেরিয়েবল আর verify-এ প্রভাব ফেলে না, যা তখন বান্ডল করা সার্টিফিকেট স্টোরে ফিরে যায়। আপনার প্রতিষ্ঠান নিজের CA দিয়ে TLS সমাপ্ত করলে সেই ফলব্যাক একটি যাচাই ত্রুটি তোলে যা আপনি এইমাত্র করা পরিবর্তনের সঙ্গে সম্পর্কহীন মনে হয়। verify স্পষ্টভাবে পাঠানোই দুটি প্রভাবকে আলাদা রাখে।
যা করা উচিত নয় তা হলো ফলাফল ত্রুটিটি চুপ করাতে verify=False সেট করা। এটি প্রক্সির ভুল কনফিগারেশনের বিনিময়ে একটি অযাচাইকৃত সংযোগ নেয় এবং বাদ দেওয়াটি যে সার্টিফিকেট সমস্যা প্রকাশ করার কথা ছিল তা লুকায়।
ব্যর্থ স্তরটি যাচাই করুন এবং রোলব্যাক রাখুন
তিনটি ব্যর্থতা লগে একই রকম দেখায় এবং তাদের মধ্যে কোনো মিল নেই: গন্তব্যে পৌঁছাতে না পারা প্রক্সি ProxyError তোলে বা 502 ফেরায়, বিশ্বাসের সমস্যা SSLError তোলে, আর অ্যাপ্লিকেশনের প্রত্যাখ্যান 401 বা 403 ফেরায়। কোনটি আপনার ক্ষেত্রে তা দেখতে Requests-এর বাইরে অনুরোধটি পুনরুৎপাদন করুন। নিচের কমান্ডগুলো প্রক্সি সরায়, সার্টিফিকেট চেইন পরীক্ষা করে, তারপর লাইব্রেরির মধ্য দিয়ে কলটি পুনরাবৃত্তি করে।
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 কল সফল হয়ে Python কল ব্যর্থ হলে পার্থক্য এখনও পরিবেশ। দুটোই TLS পর্যায়ে ব্যর্থ হলে প্রক্সি কখনোই সমস্যা ছিল না, সমস্যা সার্টিফিকেট চেইন। দুটোই 401 ফেরালে অনুরোধটি অ্যাপ্লিকেশনে পৌঁছেছে এবং বাকি কাজ প্রমাণীকরণ। তিনটির মধ্যে কোনটি দেখলেন তা লিখে রাখলে পরের মানুষটির এক ঘণ্টা বাঁচে।
রোলব্যাক যেকোনো দিকে এক লাইন: বাদ দেওয়াটি সরান, অথবা trust_env ফিরিয়ে দিন। NO_PROXY-এ যোগ করার আগে আগের মানটি সংরক্ষণ করুন, এবং শুধু আপনার টার্মিনাল ইতিহাসে বাঁচা এক্সপোর্টের বদলে র্যাপার স্ক্রিপ্ট বা ইউনিট-স্তরের Environment= এন্ট্রি পছন্দ করুন। দুটি পরিবর্তনই প্রসেস পরিবেশে দেখা যায়, তাই রিস্টার্ট সাধারণত আপনাকে পুরোনো আচরণে ফিরিয়ে দেয়।
চারটি বিষয় নিশ্চিত করে শেষ করুন: ব্যক্তিগত URL-এর একত্রিত সেটিংসে কোনো প্রক্সি নেই, সার্টিফিকেটটি অভীষ্ট CA-এর বিপরীতে যাচাই হয়, অনুরোধটি আপনার প্রত্যাশিত স্ট্যাটাস ফেরায়, এবং পরিবর্তনটি পুনরুৎপাদনযোগ্য জায়গায় কমিট করা হয়েছে। ব্যাখ্যাহীন পরিবেশ নিয়ে সবুজ স্ক্রিপ্ট এমন এক সমাধান যা পরের মেশিনে আবার ভাঙে। এই রানবুকের কমান্ডগুলোই টিকিটে পেস্ট করার মতো।