![](/img/trans.png)
[英]python socket how to properly redirect http/s requests using the same socket connection?
[英]Using Python “requests” with existing socket connection
Python“請求”庫目前風靡一時,因為它提供了用於發出HTTP請求的漂亮界面 - 但在它下面似乎有很多層間接 - 會話,HTTP適配器,最后是urllib3的機制。
如果我已經擁有一個打開的套接字,並希望使用“請求”在該套接字下發送HTTP響應並收到回復,那么在這個抽象堆棧中哪里是干預的正確位置?
如果沒有某種干預(或自定義?),堆棧將嘗試為我創建一個新的TCP / IP套接字,但在我的特定應用程序中,我的代碼在代表我已建立連接之前不會被調用,所以我會如果我想能夠使用請求的功能,需要說服請求在現有套接字上進行通話。
請求庫:
以下代碼需要來自git的requests.packages.urllib3.poolmanager.PoolManager._new_pool()
尤其是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')
直接進入urllib3
庫; 它在urllib3.connectionpool
模塊中擁有一個連接池。
您可以替換池或通過黑客池poolmanager
模塊來調整它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.