1

我在 Python 2.7 中使用 gae,在升级到 gae 1.7.6 后,我的单元测试被破坏了。我正在使用nose 和nosegae 进行单元测试。有谁知道发生了什么?任何想法都会非常感激。我觉得这与 webob 1.2.3 升级为 GA 有关。

    self.app.post(task['url'], params, headers)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 835, in post
    content_type=content_type)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 807, in _gen_request
    expect_errors=expect_errors)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 1118, in do_request
    self._check_status(status, res)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 1154, in _check_status
    res)
AppError: Bad response: 500 Internal Server Error (not 200 OK or 3xx redirect for http://localhost/task/request_log)
<pre>Traceback (most recent call last):
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py&quot;, line 1089, in __call__
    method(*args, **kwargs)
  File &quot;/Users/***/projects/game_server/game_service/events.py&quot;, line 184, in post
    inputs = pickle.loads(self.request.body)
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 677, in _body__get
    self.make_body_seekable() # we need this to have content_length
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 922, in make_body_seekable
    self.copy_body()
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 945, in copy_body
    self.body = self.body_file.read(self.content_length)
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 1528, in readinto
    + &quot;(%d more bytes were expected)&quot; % self.remaining
DisconnectionError: The client disconnected while sending the POST/PUT body (151 more bytes were expected)
</pre>
    self.app.post(task['url'], params, headers)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 835, in post
    content_type=content_type)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 807, in _gen_request
    expect_errors=expect_errors)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 1118, in do_request
    self._check_status(status, res)
  File "/Library/Python/2.7/site-packages/WebTest-1.4.0-py2.7.egg/webtest/app.py", line 1154, in _check_status
    res)
AppError: Bad response: 500 Internal Server Error (not 200 OK or 3xx redirect for http://localhost/task/request_log)
<pre>Traceback (most recent call last):
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py&quot;, line 1089, in __call__
    method(*args, **kwargs)
  File &quot;/Users/***/projects/game_server/game_service/events.py&quot;, line 184, in post
    inputs = pickle.loads(self.request.body)
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 677, in _body__get
    self.make_body_seekable() # we need this to have content_length
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 922, in make_body_seekable
    self.copy_body()
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 945, in copy_body
    self.body = self.body_file.read(self.content_length)
  File &quot;/Users/***/Downloads/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webob-1.2.3/webob/request.py&quot;, line 1528, in readinto
    + &quot;(%d more bytes were expected)&quot; % self.remaining
DisconnectionError: The client disconnected while sending the POST/PUT body (151 more bytes were expected)
</pre>
4

2 回答 2

1

短版: headers可能包含不正确的 Content-Length;像这样修复它(假设params是 a str):

fixed_header = ('Content-Length', str(len(params)))
for i, header in enumerate(headers):
    if header[0] == 'Content-Length':
        headers[i] = fixed_header
        fixed_header = None
        break
if fixed_header:  # in case you're completely missing a Content-Length header
    headers.append(fixed_header)

GAE 1.7.6将默认 webob 从 v0.9 更改为 v1.2.3。用于检索请求参数的代码(例如 via webob.Request.get())在这些版本之间发生了变化。

在 1.2.3 中,如果您查看BaseRequest.params它会创建一个NestedMultiDictusingBaseRequest.POST来尝试读取请求的主体,使用该主体来cgi.FieldStorage()检查 Content-Length 标头。如果 Content-Length 不正确,你会得到DisconnectionError你所体验的。

在 0.9 中,Request.params是使用Request.str_paramswhich 构建它的NestedMultiDictusing Request.str_POST(不同于 1.2.3)。Request.body_ file这反过来又使用了使用 with 读取的预先存在的数据,StringIO() 而没有检查 Content-Length 标头

因此,您可以在 1.7.5 中使用不正确的 Content-Length 标头,但在 1.7.6 中则不然。

任务队列数据采用 Base64 编码。我怀疑params您在回溯的第一行中传递的内容已从其 Base64 格式解码,但您没有更新 Content-Length 标头headers以反映这一点。我怀疑您从任务队列存根中获得的任务中获取了标头,该GetTasks()存根的 Content-Length 设置为原始 Base64 编码数据的长度。

于 2013-09-20T23:11:09.260 回答
0

您发送的请求可能缺少正确的 Content-Length 标头。

没有它,服务器无法准确确定客户端是否已上传所有数据,或者他是否在传输过程中断开连接。

于 2013-03-22T20:18:50.630 回答