Большие данные POST повреждены при использовании Django / PyISAPIe / IIS - PullRequest
2 голосов
/ 27 марта 2012

У меня проблема с большими данными POST (> 16384 байта) при использовании Django 1.2.3, PyISAPIe v1.1.0-rc4 и IIS 7.5.

Например, при подаче ок. 60 КБ данных формы с использованием POST, происходит следующее:

  • Первый 16-килобайтный блок данных POST верен
  • Следующий блок 16 КБ является повторением первого блока
  • Следующие 16 КБ - это еще одно повторение первого блока
  • Остальное (<16 кБ) снова верно </li>

Интересно то, что при использовании content-type="multipart/form-data" он работает нормально.

Используя эту информацию, я отследил вероятное местоположение ошибки до WSGIRequest._get_raw_post_data в django \ core \ handlers \ wsgi.py, который обрабатывает content-type="multipart/form-data" отдельно от случая по умолчанию (без содержимого).

Оба случая читаются из self.environ['wsgi.input'], для которого задан объект PyISAPIe. Разница в том, что регистр по умолчанию, кажется, читается в блоках по 16 КБ, тогда как многочастный обработчик, кажется, читает в блоках чуть менее 2 ГБ.

Я недостаточно знаю о C и интерфейсе Python для C, чтобы копать дальше, но я предполагаю, что ошибка где-то в PyISAPIe в функции ReadClient в ReadWrite.cpp.

Мой текущий обходной путь - добавить content-type="multipart/form-data" к формам, которые могут содержать более 16 КБ данных.

Кто-нибудь тоже сталкивался с этим, или кто-нибудь знает, как определить, действительно ли ошибка в PyISAPIe?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 28 марта 2012

Автор PyISAPIe здесь.

Это было исправлено в ревизии 184 в хранилище, но не в загружаемом выпуске, как обсуждалось в списке рассылки .

В нем исправлена ​​ ранее задокументированная ошибка , которая, по-видимому, не получила большого внимания, поскольку многие пользователи проверяют источник, а не скачивают пакет.Или, в любом случае, это мое лучшее предположение;Тем не менее, я планирую предоставить загружаемую версию исправленного кода.

Спасибо за то, что обратили на это мое внимание, чтобы мне напомнили о том, что я хочу поддерживать выпуски этого проекта в рабочем состоянии.

1 голос
/ 27 марта 2012

Я вырыл немного глубже, и я думаю, что нашел проблему.

В 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), новые данные правильно считываются в данные позже в коде.

Все еще не уверены, как это исправить, но по крайней мере я могу обойти это, читая в большом объемедостаточно фрагментов данных, чтобы один блок мог их прочитать.

...