使用Django / PyISAPIe / IIS时,大的POST数据已损坏

使用Django 1.2.3,PyISAPIe v1.1.0-rc4和IIS 7.5时,我遇到了大POST数据(> 16384字节)的问题。

例如,提交约。 使用POST的60kB表单数据,发生以下情况:

  • 第一个16kB的POST数据块是正确的
  • 下一个16kB块是第一个块的重复
  • 接下来的16kB是第一个块的另一个重复
  • 剩下的(<16kB)再次正确

有趣的是,当使用content-type="multipart/form-data" ,它工作正常。

使用此信息,我在django \ core \ handlers \ wsgi.py中跟踪了错误的可能位置到WSGIRequest._get_raw_post_data,它与默认值分开处理content-type="multipart/form-data" (无内容类型) ) 案件。

这两种情况都是从self.environ['wsgi.input']读取的,它被设置为PyISAPIe对象。 区别在于默认情况似乎是以16kB的块读取,而多部分处理程序似乎读取的块数略低于2GB。

我不太了解C和Python的C接口以进一步挖掘,但我猜这个bug是在ReadWrite.cpp的ReadClient函数中的PyISAPIe中的某个地方。

我目前的解决方法是将content-type="multipart/form-data"到可能产生超过16kB数据的表单中。

有没有人遇到这个,或者有人知道如何确定这个错误是否实际上在PyISAPIe中?

谢谢!

PyISAPIe作者在这里。

这已在存储库中的修订版184中修复,但未在可下载版本中修复,如邮件列表中所述 。

它解决了之前记录的错误,显然没有引起太多关注,因为许多用户正在检查源而不是下载包。 或者,这是我最好的猜测; 无论如何,我打算提供一个可下载的固定代码版本。

感谢您引起我的注意,因此我可以提醒您将此项目的版本保持在正常运行状态。

我挖得更深一些,我想我发现了这个问题。

在PyISAPIe \ Readwrite.cpp中:

 PyISAPIe_Func(DWORD) ReadClient( Context &Ctx, DWORD Length, void *const Data ) { if ( !Length ) Length = Ctx.ECB->cbTotalBytes; if ( !Data ) // Return the size of the the data that would be read return min(Length, Ctx.ECB->cbTotalBytes); DWORD Ret, Total = 0; if ( Length > Ctx.ECB->cbAvailable ) { [...snip...] } else { memcpy(Data, Ctx.ECB->lpbData, Length); Ctx.ECB->cbTotalBytes -= Length; Ctx.ECB->cbAvailable -= Length; return Length; } 

如果使用Length <= Ctx.ECB-> cbAvailable重复调用该方法,则它似乎始终将Ctx.ECB-> lpbData缓冲区的开头复制到Data中,而不是从缓冲区中删除该数据或推进指针。 只有当数据耗尽时(cbAvailable == 0),新数据才会在代码中稍后正确读入数据。

仍然不确定如何解决它,但至少我可以通过读取足够大的数据块来解决它,以便一个块将读取它。