2013-02-02 3 views
12

파이썬 "요청"라이브러리는 현재 HTTP 요청을 제공하는 아름다운 인터페이스로 인해 분노하고 있습니다.하지만 그 아래에는 많은 계층의 간접적 인 것으로 보인다 - 세션 , HTTP 어댑터, 그리고 마지막으로 urllib3의 메커니즘.기존 소켓 연결로 파이썬 "요청"사용하기

개방 소켓을 이미 보유하고있는 경우이 추상화 스택이 개입 할 수있는 곳이 며 "요청"을 사용하여 소켓에서 HTTP 응답을 보내고 회신을 다시 받으려는 경우 어떻게해야합니까?

어떤 종류의 개입 (또는 사용자 정의?)없이 스택이 나를 위해 새로운 TCP/IP 소켓을 만들려고 시도하지만 내 특정 응용 프로그램에서 내 코드가 연결을 설정할 때까지 호출되지 않습니다 요청의 기능을 사용할 수있게하려면 Requests가 기존 소켓에 대해 이야기하도록 설득해야합니다.

요청 라이브러리 :

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

https://github.com/kennethreitz/requests

답변

8

다음 코드는 연결이 표준 라이브러리에서 HTTPLIB에 의해 urllib3 열이 아닌 것을, 사실을 ncat -v -l 127.0.0.1 8000

문제이다 사용하여 자식 내가 그것을 테스트 (특히 requests.packages.urllib3.poolmanager.PoolManager._new_pool())

을 요청 필요 .

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

편집 : connectionpool의

또는 직접 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') 
+0

이 monkeypatching 나를 위해 작동하지 않습니다. 지난 4 년 동안 요청이 변경되었거나 수업이 변경되지 않았다면 잘 모르겠다. (적어도 __init__와 connect 메소드는 호출되지 않는다.) 파이썬 3.5 및 요청 2.18.1 사용하고 있습니다. – Tom