You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不修改requests的client.py下正确解析HTTP/0.9服务器响应?

解决requests无法解析HTTP/0.9响应的问题

你的问题根源在于requests依赖的urllib3默认仅支持HTTP/1.0及以上协议,而HTTP/0.9响应没有状态行(如HTTP/1.1 200 OK)和响应头,直接返回HTML内容,导致urllib3触发BadStatusLine错误。以下是两种无需修改requests源码的解决方案:


方案一:使用原生Socket手动处理请求(轻量场景)

直接用socket构造POST请求、建立SSL连接,手动读取所有响应内容(HTTP/0.9无Content-Length,数据直到连接关闭)。

import ssl
import socket

uid = "3491282510"
url_path = f'/goform/formPostData?LE=ethPortCfg&UID={uid}'
host = '10.97.80.44'
port = 443

# 编码表单数据
form_data = '&'.join([f'{k}={v}' for k, v in {
    'fd0': '0/2',
    'fd1': 'Port 2',
    'fd2': '0/2',
    'fd3': '1000X',
    'fd4': 'Disabled',
    'fd5': 'On',
    'fd6': '1G',
    'fd7': 'Full',
    'fd8': 'Off',
    'fd9': 'Off',
    'fd10': 'On',
    'fd11': 'Do nothing',
    'fd12': 'N/A',
    'fd13': '5',
    'choice': 'Apply'
}.items()])
content_length = len(form_data)

# 构造HTTP/1.1 POST请求(服务器接受HTTP/1.x请求但返回0.9响应)
request = (
    f'POST {url_path} HTTP/1.1\r\n'
    f'Host: {host}\r\n'
    f'User-Agent: Mozilla/5.0\r\n'
    f'Accept: application/xhtml+xml\r\n'
    f'Accept-Language: en-US,en;q=0.5\r\n'
    f'Accept-Encoding: gzip, deflate, bz\r\n'
    f'Content-Type: application/x-www-form-urlencoded\r\n'
    f'Content-Length: {content_length}\r\n'
    f'Connection: close\r\n'
    f'\r\n'
    f'{form_data}'
).encode('utf-8')

# 建立不验证证书的SSL连接
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE

with socket.create_connection((host, port)) as sock:
    with context.wrap_socket(sock, server_hostname=host) as ssock:
        ssock.sendall(request)
        # 读取所有响应数据
        response_data = b''
        while chunk := ssock.recv(4096):
            response_data += chunk

# HTTP/0.9响应直接是内容,无需解析状态码
print("响应内容:")
print(response_data.decode('utf-8'))

方案二:自定义requests适配器(保留requests生态)

通过继承HTTPAdapter重写响应构建逻辑,捕获BadStatusLine错误后,伪造一个包含原始响应内容的HTTP/1.1响应,让requests可以正常解析。

import requests
from requests.adapters import HTTPAdapter
from urllib3.response import HTTPResponse
from urllib3.exceptions import BadStatusLine

class HTTP09Adapter(HTTPAdapter):
    def build_response(self, req, resp):
        try:
            # 先尝试正常解析HTTP/1.x响应
            return super().build_response(req, resp)
        except BadStatusLine as e:
            # 捕获状态行错误,读取全部响应数据
            full_response = e.line.encode('utf-8')
            while chunk := resp.read(4096):
                full_response += chunk
            # 构造伪造的200响应,将原始内容作为响应体
            fake_resp = HTTPResponse(
                body=full_response,
                headers={},
                status=200,
                preload_content=False,
                decode_content=False,
                original_response=resp._original_response
            )
            return super().build_response(req, fake_resp)

# 初始化会话并挂载自定义适配器
session = requests.Session()
session.mount('https://', HTTP09Adapter())
session.verify = False  # 跳过证书验证

uid = "3491282510"
url = f'https://10.97.80.44/goform/formPostData?LE=ethPortCfg&UID={uid}'

headers = {
    "User-Agent": "Mozilla/5.0",
    "Accept": "application/xhtml+xml",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, bz"
}

data = {
    'fd0': '0/2',
    'fd1': 'Port 2',
    'fd2': '0/2',
    'fd3': '1000X',
    'fd4': 'Disabled',
    'fd5': 'On',
    'fd6': '1G',
    'fd7': 'Full',
    'fd8': 'Off',
    'fd9': 'Off',
    'fd10': 'On',
    'fd11': 'Do nothing',
    'fd12': 'N/A',
    'fd13': '5',
    'choice': 'Apply'
}

response = session.post(url, headers=headers, data=data)
print("状态码:", response.status_code)
print("响应内容:", response.text)

注意事项

  1. HTTP/0.9没有状态机制,只能默认响应为成功(状态码200),无法从响应中获取错误状态。
  2. 方案二保留了requests的所有特性(如会话持久化、自动表单编码),更适合复杂场景;方案一无需依赖requests,适合简单需求。

内容的提问来源于stack exchange,提问作者RikyR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:44:53