使用Python“;请求”;与现有的插座连接

使用Python“;请求”;与现有的插座连接,python,http,sockets,python-requests,Python,Http,Sockets,Python Requests,Python“请求”库目前风靡一时,因为它提供了用于发出HTTP请求的漂亮接口——但在它下面似乎有许多层的间接寻址——会话、HTTP适配器,最后还有urllib3的机制 如果我已经持有一个打开的套接字,并且希望使用“请求”沿该套接字发送HTTP响应并接收回复,那么在这个抽象堆栈中,哪里是干预的正确位置 在没有某种干预(或定制?)的情况下,堆栈将尝试为我创建一个新的TCP/IP套接字,但在我的特定应用程序中,在代表我建立连接之前,不会调用我的代码,因此,如果我想使用请求的特性,我需要说服请求在现有

Python“请求”库目前风靡一时,因为它提供了用于发出HTTP请求的漂亮接口——但在它下面似乎有许多层的间接寻址——会话、HTTP适配器,最后还有urllib3的机制

如果我已经持有一个打开的套接字,并且希望使用“请求”沿该套接字发送HTTP响应并接收回复,那么在这个抽象堆栈中,哪里是干预的正确位置

在没有某种干预(或定制?)的情况下,堆栈将尝试为我创建一个新的TCP/IP套接字,但在我的特定应用程序中,在代表我建立连接之前,不会调用我的代码,因此,如果我想使用请求的特性,我需要说服请求在现有套接字上进行对话

图书馆:


直接进入
urlib3
库;它在中保存一个连接池


您可以替换池或通过破解池来调整池。

以下代码需要来自git的请求(尤其是
requests.packages.urllib3.poolmanager.poolmanager.\u new\u 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')
编辑:

或直接修补连接池:

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

这个猴子补丁对我不起作用。我不确定在过去的四年里它是否工作过或者请求是否发生了变化,但我的类只是没有被使用(至少,它的
\uuuu init\uuuu
connect
方法从未被调用)。我使用的是python 3.5和请求2.18.1。