2

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

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

  • POST 数据的前 16kB 块是正确的
  • 下一个 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 和 C 语言的 Python 接口知之甚少,无法进一步深入研究,但我猜这个 bug 可能在 PyISAPIe 中 ReadWrite.cpp 的 ReadClient 函数中的某个地方。

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

是否有人也遇到过这种情况,或者有人知道如何确定该错误是否确实存在于 PyISAPIe 中?

谢谢!

4

2 回答 2

3

PyISAPIe 作者在这里。

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

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

感谢您引起我的注意,因此可以提醒我保持该项目的发布处于正常运行状态。

于 2012-03-28T05:39:09.547 回答
1

我挖得更深了,我想我找到了问题所在。

在 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。

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

于 2012-03-27T15:41:14.837 回答