
छोटी Python लाइब्रेरी जो Requests के साथ वेब ऐप्स में रेस कंडीशन का दोहन करना आसान बनाती है।
Requests-Racer एक छोटी Python लाइब्रेरी है जो आपको Requests लाइब्रेरी का उपयोग करके कई अनुरोध सबमिट करने की सुविधा देती है, जिन्हें उनके गंतव्य सर्वरों द्वारा लगभग एक ही समय पर संसाधित किया जाएगा, भले ही अनुरोधों के गंतव्य अलग-अलग हों या उनके पेलोड के आकार अलग-अलग हों। यह वेब अनुप्रयोगों में रेस कंडीशन (race condition) कमजोरियों का पता लगाने और उनका शोषण करने में सहायक हो सकता है। (अधिक जानकारी के लिए, motivation.md देखें।)
Requests (और urllib3, जिसका उपयोग Requests आंतरिक रूप से करता है) को कभी भी आपको इस तरह का कुछ करने की अनुमति देने के लिए नहीं बनाया गया था। इसलिए Requests-Racer को अनुरोधों को सबमिट करने के तरीके पर सूक्ष्म-स्तरीय नियंत्रण पाने के लिए कुछ काफी खराब हैक्स (hacks) का सहारा लेने के लिए मजबूर होना पड़ता है।
इन हैक्स में कुछ urllib3 ऑब्जेक्ट्स की निजी स्थिति (private state) के साथ छेड़छाड़ करना शामिल है, इसलिए एक urllib3 अपडेट जो अपने सार्वजनिक API के संबंध में पिछड़ा-संगत (backwards-compatible) है, फिर भी Requests-Racer को तोड़ सकता है। इसलिए, मैं Requests-Racer का उपयोग virtualenv में करने और इसे Requests या urllib3 से पहले स्थापित करने की अनुशंसा करता हूँ, ताकि इन लाइब्रेरियों का एक ज्ञात-संगत (known-compatible) संस्करण निर्भरता के रूप में खिंच जाए।
Requests-Racer का उपयोग करने के लिए, आपको Python 3.5 या उसके बाद के संस्करण की आवश्यकता होगी। पहले, एक Python वर्चुअल वातावरण बनाएँ और सक्रिय करें:
python3 -m venv env
source env/bin/activate
फिर लाइब्रेरी की एक प्रति डाउनलोड करें और इसे स्थापित करें:
git clone https://github.com/nccgroup/requests-racer.git
cd requests-racer
python setup.py install
Requests-Racer, Requests के लिए एक वैकल्पिक Transport Adapter प्रदान करके काम करता है जिसे SynchronizedAdapter कहा जाता है। यह उन सभी अनुरोधों को एकत्र करेगा जो आप इसके माध्यम से करते हैं और उन्हें केवल तभी पूरा करेगा जब finish_all() विधि को कॉल किया जाएगा:
import requests
from requests_racer import SynchronizedAdapter
s = requests.Session()
sync = SynchronizedAdapter()
s.mount('http://', sync)
s.mount('https://', sync)
resp1 = s.get('http://example.com/a', params={'hello': 'world'})
resp2 = s.post('https://example.net/b', data={'one': 'two'})
# at this point, the requests have been started but not finished.
# resp1 and resp2 should *not* be used.
sync.finish_all()
print(resp1.status_code)
print(resp2.text)
अपने कोड को सरल बनाने के लिए, आप SynchronizedSession का भी उपयोग कर सकते हैं, जो केवल एक requests.Session ऑब्जेक्ट है जो HTTP[S] के लिए स्वचालित रूप से एक SynchronizedAdapter माउंट करता है और finish_all() विधि को प्रॉक्सी करता है, इसलिए उपरोक्त कोड को इस प्रकार फिर से लिखा जा सकता है:
from requests_racer import SynchronizedSession
s = SynchronizedSession()
resp1 = s.get('http://example.com/a', params={'hello': 'world'})
resp2 = s.post('https://example.net/b', data={'one': 'two'})
# at this point, the requests have been started but not finished.
# resp1 and resp2 should *not* be used.
s.finish_all()
print(resp1.status_code)
print(resp2.text)
यहाँ कुछ सावधानियाँ (caveats) हैं जिन्हें ध्यान में रखना चाहिए और कुछ अधिक उन्नत चीज़ें जो आप कर सकते हैं:
SynchronizedAdapter थ्रेड-सुरक्षित (thread-safe) नहीं है।SynchronizedAdapter के माध्यम से किए गए अनुरोध सत्र ऑब्जेक्ट को अपडेट नहीं करेंगे (उदाहरण के लिए, Set-Cookie हेडर से कुकीज़ सत्र के कुकी जार में नहीं जोड़ी जाएँगी)।999 होगा और उसकी .text विशेषता में एक ट्रेसबैक (traceback) होगा।SynchronizedSession.from_regular_session एक requests.Session उदाहरण से SynchronizedSession का निर्माण करता है। यह तब सहायक होता है जब आपको कुछ सरल अनुरोध करने की आवश्यकता होती है, जैसे किसी सेवा में लॉग इन करना और एक सत्र कुकी प्राप्त करना जिसकी आपको सिंक्रनाइज़ अनुरोधों के लिए आवश्यकता होगी।SynchronizedAdapter और SynchronizedSession num_threads नामक एक वैकल्पिक पैरामीटर स्वीकार करते हैं, जो एडेप्टर द्वारा उपयोग किए जाने वाले थ्रेड्स की अधिकतम संख्या निर्दिष्ट करता है। यदि निर्दिष्ट नहीं किया गया है, तो एडेप्टर प्रति अनुरोध एक थ्रेड का उपयोग करेगा।प्रदर्शन संबंधी नोट्स के लिए benchmark/ देखें।
Copyright (C) 2019 Aleksejs Popovs, NCC Group
यह प्रोग्राम मुफ्त सॉफ्टवेयर है: आप इसे GNU जनरल पब्लिक लाइसेंस की शर्तों के तहत पुनर्वितरित और/या संशोधित कर सकते हैं जैसा कि फ्री सॉफ्टवेयर फाउंडेशन द्वारा प्रकाशित किया गया है, चाहे लाइसेंस का संस्करण 3 हो या (आपके विकल्प पर) कोई भी बाद का संस्करण।
यह प्रोग्राम इस उम्मीद में वितरित किया जाता है कि यह उपयोगी होगा, लेकिन बिना किसी वारंटी के; व्यापारिकता (MERCHANTABILITY) या किसी विशेष उद्देश्य के लिए उपयुक्तता (FITNESS FOR A PARTICULAR PURPOSE) की निहित वारंटी के बिना भी। अधिक विवरण के लिए GNU जनरल पब्लिक लाइसेंस देखें।
आपको इस प्रोग्राम के साथ GNU जनरल पब्लिक लाइसेंस की एक प्रति प्राप्त होनी चाहिए थी। यदि नहीं, तो https://www.gnu.org/licenses/ देखें।
finish_all() timeout नामक एक वैकल्पिक पैरामीटर स्वीकार करता है, जो अधिकतम समय (सेकंड में) निर्दिष्ट करता है जिसके लिए एडेप्टर एक थ्रेड के समाप्त होने की प्रतीक्षा करेगा।