用Python编码HTTP请求
简短版本:是否有任何简单的API用于编码HTTP请求(并解码响应),而无需作为过程的一部分实际发送和接收编码的字节 长版本:我正在编写一些嵌入式软件,它使用paramiko打开与服务器的SSH会话。然后,我需要通过使用用Python编码HTTP请求,python,http,ssh,python-requests,Python,Http,Ssh,Python Requests,简短版本:是否有任何简单的API用于编码HTTP请求(并解码响应),而无需作为过程的一部分实际发送和接收编码的字节 长版本:我正在编写一些嵌入式软件,它使用paramiko打开与服务器的SSH会话。然后,我需要通过使用transport.open\u通道('direct-tcpip',)打开的SSH通道发出HTTP请求 请求具有is传输适配器,允许您替换自己的传输。但是BaseAdapter提供的send接口只接受PreparedRequest对象,该对象(a)没有以任何有用的方式提供远程地址;
transport.open\u通道('direct-tcpip',)
打开的SSH通道发出HTTP请求
请求
具有is传输适配器,允许您替换自己的传输。但是BaseAdapter
提供的send
接口只接受PreparedRequest
对象,该对象(a)没有以任何有用的方式提供远程地址;您需要解析URL以找出主机和端口,(b)不提供请求的编码版本,只提供头和编码体(如果有)的字典。它也无法帮助您解码响应HTTPAdapter
将整个过程延迟,包括对请求进行编码、建立网络连接、发送字节、接收响应字节以及对响应进行解码,直到urllib3
urllib3
同样遵从http.client
和http.client
的HTTPConnection
类的编码和网络操作都混乱在一起
有没有一种简单的方法可以说,“给我一堆字节发送到HTTP服务器”和“这是HTTP服务器的一堆字节;将它们转换成有用的Python对象”您可以编写自己的SOCKS4代理,在本地主机上运行,然后将HTTP请求指向它。例如,描述如何将SOCKS代理与urllib3一起使用 简单的握手,然后是原始HTTP/TCP通信。握手传递目标IP地址和端口。因此,您的代理可以进行握手以使客户端确信它是SOCKS服务器,然后代理可以直接将“真实”流量发送到SSH会话(并以相反方向代理响应)
这种方法最酷的一点是,它可以处理成吨的客户机——SOCKS已经流行很长时间了。这是我能想到的最简单的实现:
from http.client import HTTPConnection
import requests
from requests.structures import CaseInsensitiveDict
from urllib.parse import urlparse
from argparse import ArgumentParser
class TunneledHTTPConnection(HTTPConnection):
def __init__(self, transport, *args, **kwargs):
self.ssh_transport = transport
HTTPConnection.__init__(self, *args, **kwargs)
def connect(self):
self.sock = self.ssh_transport.open_channel(
'direct-tcpip', (self.host, self.port), ('localhost', 0)
)
class TunneledHTTPAdapter(requests.adapters.BaseAdapter):
def __init__(self, transport):
self.transport = transport
def close(self):
pass
def send(self, request, **kwargs):
scheme, location, path, params, query, anchor = urlparse(request.url)
if ':' in location:
host, port = location.split(':')
port = int(port)
else:
host = location
port = 80
connection = TunneledHTTPConnection(self.transport, host, port)
connection.request(method=request.method,
url=request.url,
body=request.body,
headers=request.headers)
r = connection.getresponse()
resp = requests.Response()
resp.status_code = r.status
resp.headers = CaseInsensitiveDict(r.headers)
resp.raw = r
resp.reason = r.reason
resp.url = request.url
resp.request = request
resp.connection = connection
resp.encoding = requests.utils.get_encoding_from_headers(response.headers)
requests.cookies.extract_cookies_to_jar(resp.cookies, request, r)
return resp
if __name__ == '__main__':
import paramiko
parser = ArgumentParser()
parser.add_argument('-p', help='Port the SSH server listens on', default=22)
parser.add_argument('host', help='SSH server to tunnel through')
parser.add_argument('username', help='Username on SSH server')
args = parser.parse_args()
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(args.host, args.p, username=args.username)
BaseAdapter有各种各样的选项。发送它无法处理的,它完全忽略了连接池等问题,但它完成了任务。这是一个有趣的想法,但比我想要的要复杂得多。我已经想出了一个有效的方法(我将很快添加作为答案),但它似乎仍然太复杂了。TunneledHTTPAdapter在哪里使用?我在代码的任何地方都看不到它被引用。@Tom TBH我不知道。我似乎已经丢失了实现这个的代码。我需要找个时间把一台旧的笔记本电脑挖出来,如果我遇到它,我会发布更新。