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

时间:2012-03-27 14:22:36

标签: python c django python-c-api pyisapie

使用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的Python界面以进一步挖掘,但我猜这个bug是在ReadWrite.cpp的ReadClient函数中的PyISAPIe中的某个地方。

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

是否还有人遇到此问题,或者有人知道如何确定该错误是否实际上在PyISAPIe中?

谢谢!

2 个答案:

答案 0 :(得分:3)

PyISAPIe作者。

这已在存储库中的revision 184中修复,但未在可下载版本中修复,如mailing list中所述。

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

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

答案 1 :(得分: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&lt; = Ctx.ECB-&gt; cbAvailable重复调用该方法,它似乎始终将Ctx.ECB-&gt; lpbData缓冲区的开头复制到Data中,而不是从缓冲区中删除该数据或推进指针。只有当数据耗尽时(cbAvailable == 0),新数据才会在代码中稍后正确读入数据。

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