Python中与httppost请求不一致的行为

2024-05-13 18:53:28 发布

您现在位置:Python中文网/ 问答频道 /正文

尝试在Python(WSGI)和NodeJS+Express应用程序之间发出POST请求。它们在不同的服务器上。在

问题是,当使用不同的IP地址(即,专用网络与公用网络)时,公用网络上的urllib2请求成功,但是对专用网络的相同请求却以502 Bad GatewayURLError [32] Broken pipe而失败。在

我使用的urllib2代码是:

req = urllib2.Request(url, "{'some':'data'}", {'Content-Type' : 'application/json; charset=utf-8'})

res = urllib2.urlopen(req)

print f.read()

现在,我还使用^{}对请求进行了如下编码:

^{pr2}$

得到一个200 OK响应。这种替代方法适用于两个网络。在

我感兴趣的是,是否有一些我不知道的urllib2请求所需的其他配置,或者我是否需要查看一些可能丢失的网络配置(我不认为是这样,因为备用请求方法有效,但我肯定是错的)。在

如有任何建议或建议,我们将不胜感激。谢谢!在


Tags: 方法网络服务器应用程序wsginodejsurllib2post
1条回答
网友
1楼 · 发布于 2024-05-13 18:53:28

这里的问题是,正如Austin Phillips所指出的,^{}的构造函数的data参数:

may be a string specifying additional data to send to the server… data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.

通过传递JSON编码的数据而不是urlencoded的数据,您在某个地方混淆了它。在

但是,Request有一个方法^{}

Set the Request data to data. This is ignored by all handlers except HTTP handlers — and there it should be a byte string, and will change the request to be POST rather than GET.

如果您使用这个,您可能还应该使用add_header,而不是在构造函数中传递它,尽管文档中似乎没有特别提到这一点。在

所以,这应该有效:

req = urllib2.Request(url)
req.add_data("{'some':'data'}")
req.add_header('Content-Type', 'application/json; charset=utf-8')
res = urllib2.urlopen(req)

你在评论中说:

The reason I don't want to just switch over to requests without finding out why I'm seeing this problem is that there may be some deeper underlying issue that this points to that could come back and cause harder-to-detect problems later on.

如果你想找到深层次的问题,你不可能仅仅通过查看客户端源代码来实现。找出“为什么X工作而Y失败”的第一步网络代码就是精确地计算出X和Y各自发送的字节。然后,您可以尝试缩小相关差异,然后找出代码的哪一部分导致Y在相关位置发送错误的数据。在

您可以通过在服务上记录(如果您控制它的话)、运行Wireshark等等来实现这一点,但是对于简单的情况,最简单的方法是netcat。您需要为您的系统阅读man nc(而且,在Windows上,您需要在运行netcat之前获取并安装netcat),因为每个版本的语法都不同,但它总是像nc -kl 12345这样简单的东西。在

然后,在您的客户机中,更改URL以使用localhost:12345代替主机名,它将连接到netcat并发送其HTTP请求,该请求将被转储到终端。然后您可以复制它并使用nc HOST 80并粘贴它来查看实际服务器如何响应,并使用它缩小问题所在。或者,如果你被卡住了,至少你可以复制数据并粘贴到你的SO问题上。在


最后一件事:这几乎肯定与您的问题无关(因为您使用requests发送完全相同的数据,并且它正在工作),但是您的数据实际上不是有效的JSON,因为它使用单引号而不是双引号。根据the docsstring定义为:

^{pr2}$

(文档也有很好的图形表示。)

一般来说,除了非常简单的测试用例外,您不希望手工编写JSON。在很多情况下(包括你的),你所要做的就是用"…"替换json.dumps(…),所以这不是一个严重的困难。所以:

req = urllib2.Request(url)
req.add_data(json.dumps({'some':'data'}))
req.add_header('Content-Type', 'application/json; charset=utf-8')
res = urllib2.urlopen(req)

那么,它为什么起作用呢?好吧,在JavaScript中,单引号字符串是合法的,以及反斜杠转义等在JSON中无效的东西,任何使用restrictedeval(或者更糟的是raw eval)进行解析的JS代码都会接受它。而且,由于很多人都习惯于编写糟糕的JSON,因此许多浏览器的原生JSON解析器和许多其他语言的JSON库都有解决方法来允许常见错误。但你不应该依赖这个。在

相关问题 更多 >