Python 请求未对正斜杠进行编码

Python Requests Not Encoding Forward Slashes

我正在开发一种工具,需要使用 application/x-www-form-urlencoded 内容类型向站点发出请求。当我从 ARC for Chrome, I get the expected response. When I reproduce the request using requests 向 Python 3 发出请求时,我得到了完全不同的响应,这完全不是我所期望的。

我打开 WireShark 发现来自 ARC 的请求和来自 Python 脚本的请求之间的差异。来自 WireShark 的 ARC 请求的 URL-encoded 表单内容如下:

TransType=INQ&TransID=RESINQ&ReturnPage=%2Fdmvnet%2Fplate_purchase%2Fs2end.asp&HelpPage=&Choice=A&PltNo=TSPOON&HoldISA=N&HoldSavePltNo=&HoldCallHost=&NumCharsInt=8&CurrentTrans=plate_purchase_reserve&PltType=IGWT&PersonalMsg=Y&Let1=T&Let2=S&Let3=P&Let4=O&Let5=O&Let6=N&Let7=&Let8=

来自 WireShark 的 URL-encoded 表单的内容,用于 Python 脚本请求如下:

TransType=INQ&TransID=RESINQ&ReturnPage=/dmvnet/plate_purchase/s2end.asp&HelpPage=&Choice=A&PltNo=TSPOON&HoldISA=N&HoldSavePltNo=&HoldCallHost=&NumCharsInt=8&CurrentTrans=plate_purchase_reserve&PltType=IGWT&PersonalMsg=Y&Let1=T&Let2=S&Let3=P&Let4=O&Let5=O&Let6=N&Let7=&Let8=

我看到的(以及差异检查器报告的)这两者之间的唯一区别是 ReturnPage。在来自 ARC 的请求中,正斜杠被转换为 %2F,而在来自 Python 脚本的请求中,它们保持未编码。 requests 库不应该执行这种编码吗?当我在 Python 中使用原始字符串时,%2F 本身会被编码 (ReturnPage=%252Fdmvnet%252Fplate_purchase%252Fs2end.asp)。 requests 库中缺少编码在这里是否重要?

使用application/x-www-form-urlencodedheader...

headers = {
    "content-type": "application/x-www-form-urlencoded"
}

body = {
    ...
}

response = requests.post("myUrlHere", data=body, headers=headers)

使用requests从Python脚本返回的响应如下:

Status Code: 200
Headers: {
    'Cache-Control': 'private',
    'Content-Type': 'text/html',
    'Server': '',
    'Set-Cookie': 'WebSessionDataID=20200816233709078125172161292511; path=/, ASPSESSIONIDQERAATBR=ODECNAOABGCGADAJEMCCNIDM; secure; path=/',
    'Date': 'Mon, 17 Aug 2020 03: 37: 08 GMT', 'Content-Length': '0'
},
Content: "" (Empty)

预期的响应是 302 Object 移动,响应中提供了请求资源的目的地 headers。

与正斜杠的编码无关。根据 the documentation:

By default Requests will perform location redirection for all verbs except HEAD.

这意味着如果收到 302(已找到)(或者通常是任何 3xx 响应状态代码),请求将自动重定向到接收到的位置。如果你不想要这个,同样的文件说:

If you’re using GET, OPTIONS, POST, PUT, PATCH or DELETE, you can disable redirection handling with the allow_redirects parameter:

并提供了这个例子:

>>> r = requests.get('http://github.com/', allow_redirects=False)

>>> r.status_code
301

>>> r.history
[]