【问题标题】:Simulating HTTP POST request produces unexpected result模拟 HTTP POST 请求会产生意外结果
【发布时间】:2014-03-28 14:58:33
【问题描述】:

---已解决---

原来请求正文中包含文字 r"\n" (repr: "\\n") 字符,并且由于我只是将正文复制粘贴为 Python 字符串,Python 认为我给它的是换行符而不是转义换行符人物。

导致Bad Request 的原因如下:所以正文是 JSON,在 JSON 中,您必须根据定义转义所有换行符。因此,当服务器从原始文本加载 JSON 对象时,会引发错误,导致 Bad Request

我意识到这一点是因为 Content-Length 标头在两种情况下都不同(\n 是一个字符,而 \\\n 是两个字符,尽管 Content-Length 可能并不重要。

另外值得注意的是,当发送较低的 Content-Length 时,也会返回 Bad Request。我相信这是因为 JSON 正文被截断,并且服务器不接受重要的字符(例如右大括号或其他东西)


--- 问题:---

总结:

我正在尝试使用 Python 在我的 Firefox Web 浏览器中模拟对 bitbucket.org 的 POST 请求。这是我所做的:

  1. 使用 Firebug 跟踪 POST 请求
  2. 复制了 POST 请求标头
  3. 已复制 POST 请求正文(应用程序/json 格式)


代码:

这是我用来发布请求的代码,但它有点长而且不是很相关。我的 Content-Type 是 application/json,我的 POST 正文是 JSON 编码的字符串。

    dataString = '{"branch":"master","files":[{"path":"readme.txt","content":"ntestxx\n \n"}],"message":"readme.txt edited online with Bitbucket","parents":["465305dc4da32f91da057b65297cda9b72c"],"repository":{"full_name":"minesite/ica-i18n"},"timestamp":"2014-03-20T23:49:29.759Z","transient":false}'
    headers = {'X-CSRFToken': '6TqWjCl698U99Iu6ZYGBAloCxZ', 'Content-Length': '2190', 'Accept-Language': 'en,en-us;q=0.7,zh;q=0.3', 'X-NewRelic-ID': 'VwMGVVZSGwIIUFBQDwU=, VwMGVVZSGwIIUFBQDwU=', 'Cookie': 'csrftoken=6TqWjCl698U99Iu6ZYGBAloCxZ; __utma=254090395.1171276563.1394767875.1394776803.1395358874.3; __utmc=254090395; __utmz=254090395.1394776803.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); bb_session=gpqergylgoa7icpwosqsbpxig0; __utmv=254090395.|1=isBBUser=true=1; recently-viewed-repos_1701252=3802872%2C108928; __utmb=254090395.21.9.1395359363952', 'Connection': 'keep-alive', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:27.0) Gecko/20100101 Firefox/27.0', 'Host': 'bitbucket.org', 'X-Requested-With': 'XMLHttpRequest', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', 'Referer': 'https://bitbucket.org/xxxxxx/xxxxxxx/src/465305dc4da32f91da057b6529a8e4/readme.txt?at=master', 'Content-Type': 'application/json; charset=UTF-8', 'Accept-Encoding': 'gzip, deflate'}
    edit = requests.post("https://bitbucket.org/!api/internal/repositories/xxxxxxx/xxxxxxxx/oecommits/", data=dataString, headers=headers)


结果与预期结果:

当我使用我的 Firefox Web 浏览器(使用 Firebug 的“重新发送请求”功能)执行 POST 请求时,我得到一个 409 CONFLICT 响应(这是所需的响应!我正在模拟对在线编辑器的请求,所以应该是对重新发送的编辑的正确回应)。

但是,当我尝试通过复制请求标头和请求正文来模拟请求时,我得到一个 400 BAD REQUEST 响应,并且响应不包含其他信息,所以我什至不知道我的问题是什么。

无论我在网络浏览器中发送 POST 多少次(尽管时间戳不正确),它都能达到预期的结果,但服务器拒绝接受我使用 python 请求库发出的任何请求。


使用浏览器请求响应:

标题

HTTP/1.1 409 CONFLICT
Server: nginx/1.5.10
Date: Fri, 21 Mar 2014 00:20:55 GMT
Content-Type: text/plain
Content-Length: 45
Connection: keep-alive
x-served-by: app16
X-Render-Time: 0.558492183685
Content-Language: en
X-Static-Version: 48695e7c3140
Vary: Authorization, Accept-Language, Cookie
X-Version: e6778a5040f7
Etag: "92f0b780984e984140de0f8ed0a3992c"
X-Frame-Options: SAMEORIGIN
X-Request-Count: 483
X-NewRelic-App-Data: PxQEVFdXCAITVVlWBgMPUkYdFGQHBDcQUQxLA1tMXV1dSn8UXwJHCwtYGAMPF1pGUw8EFhlQRxYXH1dDC0gKDEQHSgxZVBpaUgtdDVQTQFgrWFsICAZ9V1kQIg1aXF4SLFBYVw4DEUxTEF0DTF0WHgNJCU8EVApUUgUHVFFQCgQCU1FXGwMGX1QdFAEBUVVbA1AJVQEBB1FSA11DHQdSDhdTag==

身体

Specified change not on head of branch master


使用 python 请求响应:

标题

content-length: 11
x-served-by: app10
x-render-time: 0.012787103653
content-language: en
content-type: text/plain
vary: Authorization, Accept-Language, Cookie
connection: keep-alive
server: nginx/1.5.10
x-version: e6778a5040f7
etag: "825644f747baab2c00e420dbbc39e4b3"
x-request-count: 321
x-newrelic-app-data: PxQEVFdXCAITVVlWBgMPUkYdFGQHBDcQUQxLA1tMXV1dSn8UXwJHCwtYGAMPF1pGUw8EFhlQRxYXH1dDC0gRB0MNTRBbXQ5gVhZWFEMCVkBIBhtRSFMJAARQUlsDBw9VXAIBC1tWVU4CUwtUFBpVAwFcWgdTVQIAXQBRWQQAGh9WBQ0RUmw=
date: Fri, 21 Mar 2014 00:51:01 GMT
x-frame-options: SAMEORIGIN
x-static-version: 48695e7c3140

身体

Bad Request


我的一些想法:

我想也许我需要模拟 HTTP POST 请求的另一个组件?也许当 Firefox 发送 POST 请求时,添加了一些标头或包装器使请求有效?

或者 POST 请求除了方法、标头和正文之外还有其他内容吗?

也许这与它是 HTTPS 而不是 HTTP 的事实有关?


更新:

我已尝试将“已发送的 cookie”与请求一起发送,但收效甚微。

【问题讨论】:

    标签: python http post firebug python-requests


    【解决方案1】:

    或者说 POST 请求不仅仅是一个方法, 标题和正文?

    没有。重要的部分是请求标头。在这两种情况下,它们应该完全相同。

    因为 Firebug 只能跟踪 Firefox 内部的网络请求,所以您需要像 Wireshark 这样的外部网络分析器来跟踪来自 Python 脚本的请求。 当然需要在脚本所在的服务器上运行。

    另一种解决方案是在本地 Web 服务器上运行您的请求并在那里记录请求信息。

    然后您就可以将浏览器中发出的请求与脚本中的请求进行比较。

    【讨论】:

    • 谢谢!我一定会尝试的。我尝试查看 Wireshark,但有太多(看似编码的)数据包,我不知道应该阅读哪些数据包
    • 哦,是的。我错过了您正在访问 HTTPS URL。所以你可以看看wiki.wireshark.org/SSL 来解密请求信息。
    • 解决了!原来我的请求正文被错误地转录,导致内容长度标题不正确。你的帮助太棒了,非常感谢
    猜你喜欢
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多