未读取请求正文时的 ERR_INCOMPLETE_CHUNKED_ENCODING
Posted
技术标签:
【中文标题】未读取请求正文时的 ERR_INCOMPLETE_CHUNKED_ENCODING【英文标题】:ERR_INCOMPLETE_CHUNKED_ENCODING when the request body is not read 【发布时间】:2017-03-25 22:53:38 【问题描述】:以下是我对一个有趣的错误的讨伐记录,虽然我已经解决了,但我不明白。我找到了一个解决方案,但我真的希望有人能提供一些关于该错误的实际原因的见解。
问题背景
这个问题首先出现在我们的 Django 应用的生产服务器上。堆栈如下
AngularJS nginx uWSGI 姜戈 PostgreSQL我们的团队发现 Safari 上的单个 POST 请求存在问题。 Safari 会阻塞响应并吐出ERR_INCOMPLETE_CHUNKED_ENCODING
。 post请求如下:
class ContractCloseOutSubmitView(APIView):
def post(self, request, contract_id):
contract = get_object_or_404(
ContractCloseOut, pk=contract_id)
if contract.submit():
return Response("detail": "Closed successfully.", status=200)
else:
raise ParseError("Could not submit.")
请求是将对象标记为关闭的简单请求。我们在网站的很多地方都使用了这种模式,所以这个问题显然需要注意。
解决方案
我们的第一个线索是请求确实关闭了对象。也就是说,必须到达if contract.submit()
行。这将问题缩小到响应范围。我做了一些阅读,这个错误有很多原因。我们试过了:
没有任何效果,问题仍然没有在本地发生。所以我们决定在本地复制整个堆栈并进行测试。一次一个,我们删除了网络层的元素,并确定删除 nginx 并直接与 uWSGI 对话解决了这个问题。
所以现在我们确信问题出在 nginx 上,但仍然没有解决方案。好吧,在 Google 的第三页深处,我看到了一篇 *** 帖子,其中有一个简短的评论,提到 读取请求正文 对 nginx 的缓冲区以及它如何判断内容长度有某种影响(这是我不太熟悉的东西)。无论如何,显然解决此问题的方法是简单地读取缓冲区。也就是说,使用请求正文。所以我尝试通过将其值分配给变量来简单地触摸请求正文:
class ContractCloseOutSubmitView(APIView):
def post(self, request, contract_id):
data = request.data #touchie touchie
contract = get_object_or_404(
ContractCloseOut, pk=contract_id)
if contract.submit():
return Response("detail": "Closed successfuly.", status=200)
else:
raise ParseError("Could not submit.")
tl;博士
在收到对一个非常简单的呼叫的响应时遇到ERR_INCOMPLETE_CHUNKED_ENCODING
问题仅发生在生产环境中的 Safari 中
在调试时,我们一次删除了一部分堆栈,并确定删除 nginx 可以解决问题
请求是 POST,但请求正文中没有信息,因此正文被忽略
我发现一个 *** 问题的评论提到读取 POST 请求的正文对 nginx 的请求缓冲区有某种影响
只需将请求正文分配给一个变量(从而读取缓冲区)即可解决问题
在这一切之后,我只是想知道为什么会发生这种情况。不读取可能导致此错误的请求正文是什么?为什么只有nginx?为什么只有 Safari?
我希望 *** 社区可以帮助我解释这一点!解决起来很有趣。我还做了一个简短的presentation 与一些同事分享。
【问题讨论】:
【参考方案1】:您没有指定 nginx 的版本。如果几个月没有更新,可能是这个已关闭的issue:
https://trac.nginx.org/nginx/ticket/959
以前,流的窗口保持为零,以防止 客户端在请求之前发送请求正文(请参阅 887cca40ba6a 了解详情)。直到这样的初始窗口被确认 所有带有数据的请求都被拒绝(有关详细信息,请参阅 0aa07850922f)。 这种方法揭示了许多问题:一些客户(尤其是 MS IE/Edge、Safari、ios 应用程序)显示错误甚至崩溃,如果 流被拒绝;这要求每个请求至少有一个 RTT 在客户端接收窗口更新并能够发送之前使用正文 数据。为了克服这些问题,新指令 介绍了“http2_body_preread_size”。它设置初始窗口 并配置一个特殊的每个流预读缓冲区,用于 在请求和处理正文之前保存所有传入数据。
我的猜测是创建引用会在设置确认来回后保持该缓冲区打开。
尝试升级 nginx,因为此补丁已合并。如果你升级后仍然有问题,这是一个回归,我会打开一个新的 nginx 票。
【讨论】:
有趣。它已经几个月没有更新了。这可能只是它!我正在为这个 bug 做一个概念证明,所以我会看看我是否可以将它隔离到 nginx 版本。以上是关于未读取请求正文时的 ERR_INCOMPLETE_CHUNKED_ENCODING的主要内容,如果未能解决你的问题,请参考以下文章