使用Python“请求”与现有的插座连接(Using Python “requests” with

2019-07-19 03:52发布

Python的“请求”图书馆是目前所有的愤怒,因为漂亮的界面,它提供了HTTP请求的 - 但它的下面似乎有间接的许多层 - 会话,HTTP适配器和urllib3终于机制。

凡在本组抽象的是,如果我已经持有一个开放的插座,想用“请求”派下来的套接字的HTTP响应,并收到回复给介入正确的地方?

如果没有某种形式的干预(或定制?)的,堆栈会尽力为我创建一个新的TCP / IP套接字,但在我的特定应用我的代码不叫,直到连接已经代表我的建立,所以我会需要说服请求谈论现有插座上,如果我想能够使用要求的特点。

该请求库:

http://pypi.python.org/pypi/requests

https://github.com/kennethreitz/requests

Answer 1:

下面的代码需要从git的请求(尤其是requests.packages.urllib3.poolmanager.PoolManager._new_pool()

我测试了使用ncat -v -l 127.0.0.1 8000

问题是这样的事实,该连接不会被urllib3打开,但通过httplib的标准库中。

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')

编辑:

或连接池的直接的monkeypatching:

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')


Answer 2:

直奔urllib3库; 它拥有一个连接池urllib3.connectionpool模块 。

你可以更换池或由黑客进行调整poolmanager模块可能。



文章来源: Using Python “requests” with existing socket connection