2015-10-09 8 views
5

का उपयोग करने के लिए फोर्स अनुरोध requests लाइब्रेरी को अनुरोध प्राप्त करने के लिए एक विशिष्ट इंटरनेट प्रोटोकॉल संस्करण का उपयोग करने के लिए कैसे मजबूर करें? या यह पाइथन में एक और विधि के साथ बेहतर हासिल किया जा सकता है? मैं कर सकता, लेकिन मैं curl का उपयोग नहीं करना चाहते हैं ...आईपीवी 4/आईपीवी 6

उदाहरण उद्देश्य स्पष्ट करने के लिए:

import requests 
r = requests.get('https://my-dyn-dns-service.domain/?hostname=my.domain', 
       auth = ('myUserName', 'my-password')) 

उत्तर

1

यह पूरी तरह अपरीक्षित है और शायद कुछ बदलाव की आवश्यकता होगी, लेकिन Using Python “requests” with existing socket connection और how to force python httplib library to use only A requests से जवाब के संयोजन, यह आप की तरह लग रहा

try: 
    from http.client import HTTPConnection 
except ImportError: 
    from httplib import HTTPConnection 

class MyHTTPConnection(HTTPConnection): 
    def connect(self): 
     print("This actually called called") 
     self.sock = socket.socket(socket.AF_INET6) 
     self.sock.connect((self.host, self.port,0,0)) 
     if self._tunnel_host: 
      self._tunnel() 

requests.packages.urllib3.connectionpool.HTTPConnection = MyHTTPConnection 
+0

क्षमा करें, मुझे अभी भी एक आईपीवी 4 उत्तर मिलता है। मैंने 'प्रिंट (request.get ('https://icanhazip.com') .text) की कोशिश की। – ominug

+0

दुर्भाग्यवश, मेरे पास इस समय आईपीवी 6 के साथ कुछ भी नहीं है; मैंने यह सुनिश्चित करने के लिए एक प्रिंट स्टेटमेंट और एक कनेक्ट स्टेटमेंट जोड़ा है कि मुझे HTTPConnection ऑब्जेक्ट – Foon

+0

पर बंदरगाह करने के बारे में कुछ याद नहीं आया ठीक है, मैंने इसे फिर से कोशिश की। कनेक्ट विधि को नहीं कहा जाता है। – ominug

1

पिछले जवाब पढ़ने के बाद, मैं मजबूर करने के लिए कोड को संशोधित करने के लिए किया था: एक IPv6 केवल सॉकेट बनाने के लिए और फिर अनुरोधों का उपयोग ऐसा ही कुछ के साथ अपने संबंध पूल के लिए है में सक्षम होना चाहिए आईपीवी 6 के बजाय आईपीवी 4। ध्यान दें कि मैंने socket.AF_INET6 के बजाय socket.AF_INET का उपयोग किया है, और self.sock.connect() में 2-आइटम ट्यूपल तर्क है।

मैं भी HTTP एस कनेक्शन जो HTTPConnection की तुलना में बहुत अलग है के बाद से requests अगर ssl मॉड्यूल उपलब्ध है प्रमाणपत्र सत्यापित करने में httplib.HTTPSConnection लपेटता ओवरराइड करने के लिए की जरूरत है।

import socket 
import ssl 
try: 
    from http.client import HTTPConnection 
except ImportError: 
    from httplib import HTTPConnection 
from requests.packages.urllib3.connection import VerifiedHTTPSConnection 

# HTTP 
class MyHTTPConnection(HTTPConnection): 
    def connect(self): 
     self.sock = socket.socket(socket.AF_INET) 
     self.sock.connect((self.host, self.port)) 
     if self._tunnel_host: 
      self._tunnel() 

requests.packages.urllib3.connectionpool.HTTPConnection = MyHTTPConnection 
requests.packages.urllib3.connectionpool.HTTPConnectionPool.ConnectionCls = MyHTTPConnection 

# HTTPS 
class MyHTTPSConnection(VerifiedHTTPSConnection): 
    def connect(self): 
     self.sock = socket.socket(socket.AF_INET) 
     self.sock.connect((self.host, self.port)) 
     if self._tunnel_host: 
      self._tunnel() 
     self.sock = ssl.wrap_socket(self.sock, self.key_file, self.cert_file) 

requests.packages.urllib3.connectionpool.HTTPSConnection = MyHTTPSConnection 
requests.packages.urllib3.connectionpool.VerifiedHTTPSConnection = MyHTTPSConnection 
requests.packages.urllib3.connectionpool.HTTPSConnectionPool.ConnectionCls = MyHTTPSConnection 
+0

यह उत्तर मेरे लिए काम करता है, यह चेतावनी के साथ कि यह 'असुरक्षित रिवेस्ट चेतावनी: असत्यापित HTTPS अनुरोध किया जा रहा है। प्रमाण पत्र सत्यापन जोड़ना दृढ़ता से सलाह दी जाती है। देखें: https पर चलते समय https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning' – kyrenia

0

मैं https://stackoverflow.com/a/33046939/5059062 लिए एक समान दृष्टिकोण लिया, लेकिन इसके बजाय socket में बात यह है कि DNS अनुरोध करता है बाहर समझौता तो यह केवल करता है आईपीवी 6 या IPv4, हर अनुरोध, इस में इस्तेमाल किया जा सकता है जिसका मतलब है के लिए urllibrequests में प्रभावी रूप से प्रभावी रूप से।

यदि आपका प्रोग्राम यूनिक्स पाइप और अन्य ऐसी चीजों का भी उपयोग करता है तो यह बुरा हो सकता है, इसलिए मैं बंदरगाह के साथ सावधानी बरतता हूं।

import requests 
import socket 
from unittest.mock import patch 
import re 

orig_getaddrinfo = socket.getaddrinfo 
def getaddrinfoIPv6(host, port, family=0, type=0, proto=0, flags=0): 
    return orig_getaddrinfo(host=host, port=port, family=socket.AF_INET6, type=type, proto=proto, flags=flags) 

def getaddrinfoIPv4(host, port, family=0, type=0, proto=0, flags=0): 
    return orig_getaddrinfo(host=host, port=port, family=socket.AF_INET, type=type, proto=proto, flags=flags) 

with patch('socket.getaddrinfo', side_effect=getaddrinfoIPv6): 
    r = requests.get('http://ip6.me') 
    print('ipv6: '+re.search(r'\+3>(.*?)</',r.content.decode('utf-8')).group(1)) 

with patch('socket.getaddrinfo', side_effect=getaddrinfoIPv4): 
    r = requests.get('http://ip6.me') 
    print('ipv4: '+re.search(r'\+3>(.*?)</',r.content.decode('utf-8')).group(1)) 

और requests बिना:

import urllib.request 
import socket 
from unittest.mock import patch 
import re 

orig_getaddrinfo = socket.getaddrinfo 
def getaddrinfoIPv6(host, port, family=0, type=0, proto=0, flags=0): 
    return orig_getaddrinfo(host=host, port=port, family=socket.AF_INET6, type=type, proto=proto, flags=flags) 

def getaddrinfoIPv4(host, port, family=0, type=0, proto=0, flags=0): 
    return orig_getaddrinfo(host=host, port=port, family=socket.AF_INET, type=type, proto=proto, flags=flags) 

with patch('socket.getaddrinfo', side_effect=getaddrinfoIPv6): 
    r = urllib.request.urlopen('http://ip6.me') 
    print('ipv6: '+re.search(r'\+3>(.*?)</',r.read().decode('utf-8')).group(1)) 

with patch('socket.getaddrinfo', side_effect=getaddrinfoIPv4): 
    r = urllib.request.urlopen('http://ip6.me') 
    print('ipv4: '+re.search(r'\+3>(.*?)</',r.read().decode('utf-8')).group(1)) 

3.5.2

0

में परीक्षण किया गया मैं या तो आईपीवी 4 या IPv6 उपयोग करने के लिए मजबूर करने के लिए urrlib3 एक minimalistic समाधान मिल गया है। एचटीपी और एचटीपीएस दोनों के लिए नया कनेक्शन बनाने के लिए urrlib3 द्वारा इस विधि का उपयोग किया जाता है। आप इसे किसी भी AF_FAMILY में निर्दिष्ट कर सकते हैं जिसका आप उपयोग करना चाहते हैं।

import socket 
import requests.packages.urllib3.util.connection as urllib3_cn 


    def allowed_gai_family(): 
    """ 
    https://github.com/shazow/urllib3/blob/master/urllib3/util/connection.py 
    """ 
    family = socket.AF_INET 
    if urllib3_cn.HAS_IPV6: 
     family = socket.AF_INET6 # force ipv6 only if it is available 
    return family 

urllib3_cn.allowed_gai_family = allowed_gai_family 
संबंधित मुद्दे