Using Python “requests” with existing socket connection

前端 未结 2 596
感动是毒
感动是毒 2021-01-01 18:07

The Python “requests” library is currently all the rage, because of the beautiful interface that it provides for making HTTP requests — but beneath it there seems to be many

相关标签:
2条回答
  • 2021-01-01 18:29

    Go straight to the urllib3 library; it holds a connection pool in the urllib3.connectionpool module.

    You could replace the pool or adjust it by hacking the poolmanager module perhaps.

    0 讨论(0)
  • 2021-01-01 18:30

    The following code needs requests from git (especially requests.packages.urllib3.poolmanager.PoolManager._new_pool())

    I tested it using ncat -v -l 127.0.0.1 8000

    The problem is the fact, that the connection isn't opened by urllib3 but by httplib from the standard library.

    import socket
    import requests
    from requests.adapters import HTTPAdapter
    from requests.packages.urllib3 import PoolManager, HTTPConnectionPool
    
    try:
        from http.client import HTTPConnection
    except ImportError:
        from httplib import HTTPConnection
    
    
    class MyAdapter(HTTPAdapter):
        def init_poolmanager(self, connections, maxsize):
            self.poolmanager = MyPoolManager(num_pools=connections,
                                             maxsize=maxsize)
    
    
    class MyPoolManager(PoolManager):
        def _new_pool(self, scheme, host, port):
            # Important!
            if scheme == 'http' and host == my_host and port == my_port:
                return MyHTTPConnectionPool(host, port, **self.connection_pool_kw)
            return super(PoolManager, self)._new_pool(self, scheme, host, port)
    
    
    class MyHTTPConnectionPool(HTTPConnectionPool):
        def _new_conn(self):
            self.num_connections += 1
            return MyHTTPConnection(host=self.host,
                                port=self.port,
                                strict=self.strict)
    
    
    class MyHTTPConnection(HTTPConnection):
        def connect(self):
            """Connect to the host and port specified in __init__."""
            # Original
            # self.sock = socket.create_connection((self.host, self.port),
            #                                    self.timeout, self.source_address)
            # Important!
            self.sock = my_socket
            if self._tunnel_host:
                self._tunnel()
    
    
    if __name__ == '__main__':
        import time
    
        my_host = '127.0.0.1'
        my_port = 8000
    
        my_socket = socket.create_connection((my_host, my_port))
        time.sleep(4)
        s = requests.Session()
        s.mount('http://', MyAdapter())
        s.get('http://127.0.0.1:8000/foo')
    

    Edit:

    Or direct monkeypatching of the connectionpool:

    class MyHTTPConnection(HTTPConnection):
        def connect(self):
            self.sock = my_socket
            if self._tunnel_host:
                self._tunnel()
    
    requests.packages.urllib3.connectionpool.HTTPConnection = MyHTTPConnection
    
    if __name__ == '__main__':
        my_host = '127.0.0.1'
        my_port = 8000
    
        my_socket = socket.create_connection((my_host, my_port))
        requests.get('http://127.0.0.1:8000/foo')
    
    0 讨论(0)
提交回复
热议问题