大型 POST 数据在使用 Django/PyISAPIe/IIS 时损坏



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

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

  • 开机自检数据的第一个 16kB 块是正确的
  • 下一个 16kB 块是第一个块的重复
  • 下一个16kB是第一个块的另一个重复
  • 其余的(<16kB(再次正确

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

利用这些信息,我在 django\core\handlers\wsgi.py 中追踪了要WSGIRequest._get_raw_post_data的错误可能位置,它与默认(无内容类型(情况分开处理content-type="multipart/form-data"

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

我对C和Python接口的了解还不够多,无法进一步深入研究,但我猜这个错误在ReadWrite.cpp的ReadClient函数中的PyISAPIe中的某个地方。

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

有没有人也遇到过这个问题,或者有人知道如何确定该错误是否实际上在 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( 时,新数据才会在代码的后面正确读入 Data。

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

相关内容

  • 没有找到相关文章

最新更新