Почему «Content-Length: 0» в запросах POST? - PullRequest
50 голосов
/ 30 ноября 2008

Клиент иногда отправляет запросы POST с Content-Length: 0 при отправке формы (от 10 до более 40 полей).

Мы протестировали его в разных браузерах и в разных местах, но не смогли воспроизвести ошибку. Клиент использует Internet Explorer 7 и прокси.

Мы попросили их позволить системному администратору разобраться в проблеме со своей стороны. Запуск некоторых тестов без прокси и т. Д.

Тем временем (через полгода и до сих пор нет ответа) мне любопытно, знает ли кто-нибудь еще о подобных проблемах с запросом Content-Length: 0. Может быть, из какой-то сети Windows со специальным прокси для крупных компаний.

Известна ли проблема с Internet Explorer 7? С прокси системой? Сама сеть Windows?

Google показал что-то только в контексте аутентификации NTLM (и тому подобное), но мы не используем это в веб-приложении. Может быть, дело в том, как прокси работает в сети клиента с логинами Windows? (Я не эксперт по Windows. Просто думаю.)

У меня нет дополнительной информации об инфраструктуре.

ОБНОВЛЕНИЕ: В декабре 2010 года об этом можно было сообщить одному администратору, в т.ч. ссылки из ответов здесь. Контакт был из-за другой проблемы, которая также была вызвана прокси. Нет отзывов с тех пор. И сообщения об ошибках все еще там. Я смеюсь, чтобы помешать мне плакать.

ОБНОВЛЕНИЕ 2: Эта проблема существует с середины 2008 года. Каждые несколько месяцев клиент раздражен и хочет, чтобы это было исправлено как можно скорее. Мы снова отправляем им все старые электронные письма и просим их связаться с их администраторами, чтобы либо исправить это, либо провести дополнительные тесты. В декабре 2010 года мы смогли отправить некоторую информацию одному администратору. Нет отзывов. Проблема не устранена, и мы даже не знаем, пытались ли они. А в мае 2011 года клиент снова пишет и хочет, чтобы это было исправлено. Тот же человек, который имеет всю информацию с 2008 года.

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

ОБНОВЛЕНИЕ 3: Май 2012 года, и мне было интересно, почему мы не получили еще одно требование исправить это (см. ОБНОВЛЕНИЕ 2). Изучил протокол ошибок, который только сообщает об этой единственной ошибке каждый раз, когда она произошла (около 15 в день). Это прекратилось в конце января 2012 года. Никто ничего не сказал. Должно быть, они что-то сделали со своей сетью. Уже все хорошо. С лета 2008 года по январь 2012 года. Жаль, что я не могу рассказать вам, что они сделали.

ОБНОВЛЕНИЕ 4: Сентябрь 2015. Веб-сайт должен был собрать некоторые данные и доставить их на основной веб-сайт клиента. Был API с аккаунтом. Всякий раз, когда возникала проблема, они связывались с нами, даже если проблема явно была на другой стороне. Уже несколько недель мы не можем отправить им данные. Аккаунт больше не доступен. У них был перезапуск, и я больше не могу найти страницы, которые использовали данные нашего сайта. В отчете об ошибке нет ответа и никто не жалуется. Я думаю, они только что закончили этот проект.

ОБНОВЛЕНИЕ 5: Март 2017 года. API перестал работать летом 2015 года. Похоже, что клиент продолжает платить за сайт и все еще получает доступ к нему в феврале 2017 года. Я предполагаю, что они используют его как архив Они больше не создают и не обновляют данные, поэтому эта ошибка, вероятно, не возникнет после таинственного исправления в январе 2012 года. Но это будет чья-то проблема. Я ухожу.

Ответы [ 13 ]

40 голосов
/ 10 марта 2009

Internet Explorer не отправляет поля формы, если они опубликованы с сайта, прошедшего проверку подлинности (NTLM), на сайт без проверки подлинности (анонимный).

Это функция для ситуаций ответа на вызов (веб-сайты, защищенные NTLM или Kerberos), когда IE может ожидать, что первый запрос POST немедленно приведет к ответу HTTP 401 Authentication Required (который включает в себя вызов) ), и только второй запрос POST (который включает в себя ответ на вызов) будет фактически принят. В этих ситуациях IE не загружает возможно большое тело запроса с первым запросом по соображениям производительности. Спасибо EricLaw за размещение этой информации в комментариях.

Это происходит каждый раз, когда выполняется HTTP POST со страницы, прошедшей проверку подлинности NTLM (т. Е. Интрасети), на страницу без проверки подлинности (т. Е. Интернет) или, если страница без проверки подлинности является частью набора фреймов, где страница набора фреймов аутентифицирован.

Обходной путь - либо использовать запрос GET в качестве метода формы, либо убедиться, что страница, не прошедшая проверку подлинности, открыта в новой вкладке / окне (цель избранного / ссылка) без частично аутентифицированного набора фреймов. Как только модель аутентификации для всего окна будет согласованной, IE снова начнет отправлять содержимое формы.


14 голосов
/ 13 апреля 2010

Это легко воспроизвести с помощью MS-IE и фильтра аутентификации NTLM на стороне сервера. У меня та же проблема с JCIFS (1.2. ), стойками 1. и MS-IE 6/7 на XP-SP2. Это было наконец исправлено. Есть несколько обходных путей, чтобы сделать это.

  1. изменить метод формы с POST (настройка по умолчанию для стоек) на GET. Для большинства страниц с небольшими формами это работает хорошо. К сожалению, у меня есть более 50 записей для отправки в HTTP-поток обратно на сервер. IE имеет ограничение GET URL 2038 байт (не длина параметра, а вся длина URL). Так что это быстрый обходной путь, но он не применим для меня.

  2. отправить GET перед выполнением действия POST. Это было рекомендовано в MS-KB. В моем проекте много устаревших процедур, и я бы не стал рисковать в нужное время. Я никогда не пробовал этого, потому что он все еще нуждается в дополнительной обработке аутентификации, когда GET получен фильтрующим слоем на основе моего понимания из MS-KB, и я не хотел бы изменять поведение с другими браузерами, например Firefox, Opera.

  3. обнаружение, было ли отправлено сообщение POST с нулевой длиной содержимого (вы можете получить его из хеш-структуры свойств заголовка в вашей инфраструктуре). Если это так, запустите цикл проверки подлинности NTLM, получив код вызова из DC или из кэша, и ожидайте ответ NTLM. Когда получено сообщение NTLM type2 и сеанс все еще действителен, вам не нужно аутентифицировать пользователя, а просто перенаправить его на ожидаемое действие, если длина содержимого POST не равна нулю. Кстати, это увеличит трафик сети. Поэтому проверьте настройки времени жизни вашего кеша и настройки soTimeOut SMB-сессии, прежде чем применять изменения, пожалуйста. Или, проще говоря, вы можете просто отправить 401-неавторизованный статус в MS-IE, и браузер должен отправить обратно запрос POST с данными в ответ.

  4. MS-KB предоставил оперативное исправление с KB-923155 (я не мог опубликовать более одной ссылки из-за низкого числа репутаций: {), но, похоже, он не работает. Кто-нибудь опубликует здесь исправление? Спасибо :) Вот ссылка для справки, http://www.websina.com/bugzero/kb/browser-ie.html

6 голосов
/ 01 июля 2009

У нас есть клиент в нашей системе с точно такой же проблемой. Мы указали на прокси / брандмауэр. Microsoft IAS. Он удаляет тело POST и отправляет контент-длину: 0. Однако мы не можем обойтись без особых усилий и хотим использовать запросы GET, поскольку это выставляет имена пользователей / пароли и т.д. в строке URL. В нашей системе около 7000 пользователей, и только один из них имеет проблему ... также только один использует Microsoft IAS, поэтому так и должно быть.

4 голосов
/ 12 марта 2009

Скорее всего, проблема в том, что промежуточный прокси-сервер реализует HTTP 1.0.

В HTTP 1.0 вы должны использовать поле заголовка Content-Length: ( См. Раздел 10.4 здесь )

Требуется допустимая длина содержимого все запросы HTTP / 1.0 POST. HTTP / 1.0 сервер должен ответить 400 (неверный запрос) сообщение, если не может определить длину запроса содержание сообщения.

Запрос к прокси-серверу - HTTP 1.1, и поэтому ему не нужно использовать поле заголовка Content-Length. Заголовок Content-Length обычно используется, но не всегда. См. Следующую выдержку из HTTP 1.1 RFC S. 14.13 .

Приложения ДОЛЖНЫ использовать это поле для указать длину передачи тело сообщения, если это не запрещено правилами раздела 4,4 . Любая длина контента больше или равно нулю - допустимое значение.

Раздел 4.4 описывает, как определить длина тела сообщения, если Длина содержимого не указана.

Таким образом, прокси-сервер не видит заголовок Content-Length, который, как предполагается, абсолютно необходим в HTTP 1.0, если есть тело. Таким образом, он принимает 0, чтобы запрос в конечном итоге достиг сервера. Помните, что прокси не знает правил спецификации HTTP 1.1, поэтому он не знает, как справиться с ситуацией, когда нет заголовка Content-Length.

Вы на 100% уверены, что в вашем запросе указан заголовок Content-Length? Если он использует другое средство, как определено в разделе 4.4, потому что думает, что сервер 1.1 (потому что он не знает о прокси 1.0 между ними), тогда у вас будет описанная вами проблема.

Возможно, вы можете использовать HTTP GET вместо этого, чтобы обойти проблему.

3 голосов
/ 11 марта 2009

Это известная проблема для Internet Explorer 6, но не для 7, о которой я знаю. Вы можете установить это исправление для IE6 KB831167 fix.

Вы можете узнать больше об этом здесь .

Несколько вопросов к вам:

  • Вы знаете, какой тип прокси?
  • Знаете ли вы, есть ли в запросе фактическое тело?
  • Это происходит последовательно каждый раз? Или только иногда?
  • Есть ли в запросе двоичные данные? Возможно, данные начинаются с \ 0, и у прокси есть ошибка с двоичными данными.
2 голосов
/ 30 июня 2010

Если пользователь проходит через прокси-сервер ISA, использующий проверку подлинности NTLM, то это звучит как эта проблема, для которой предусмотрено решение (исправление для прокси-сервера ISA)

http://support.microsoft.com/kb/942638
POST запросы, не имеющие тела POST, могут отправляться на веб-сервер, опубликованный в ISA Server 2006

1 голос
/ 30 ноября 2008

Наличие и возможные значения заголовка ContentLength в HTTP описаны в HTTP (я полагаю, 1/1) RFC:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

В HTTP СЛЕДУЕТ отправлять всякий раз, когда длина сообщения может быть определена до его передачи

Смотри также:

Если сообщение получено с обоими Поле заголовка Transfer-Encoding и поле заголовка Content-Length, последнее ДОЛЖНО игнорироваться. http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

Может быть, ваше сообщение содержит заголовок Transfer-Encoding?

Позднее редактирование: также обратите внимание, что «СЛЕДУЕТ», как используется в RFC, очень важно и не эквивалентно «ДОЛЖНО»:

3. СЛЕДУЕТ, чтобы это слово или прилагательное «РЕКОМЕНДОВАНО» означало, что могут существовать веские причины в определенных обстоятельствах игнорировать конкретный пункт, но все последствия должны быть поняты и тщательно взвесить, прежде чем выбрать другой курс. Ссылка: http://www.ietf.org/rfc/rfc2119.txt

1 голос
/ 30 ноября 2008

Вы уверены, что эти запросы исходят от "клиента"?

У меня была эта проблема с ботами раньше; иногда они проверяют сайты на наличие форм «свяжитесь с нами», отправляя пустые запросы POST на основе URI действия в тегах FORM, которые они обнаруживают во время сканирования.

0 голосов
/ 30 июня 2017

У меня также была проблема, когда запросы от браузера IE 11 клиента имели Content-Length: 0 и не включали ожидаемый контент POST. Когда клиент использовал Firefox или Chrome, ожидаемый контент был включен в запрос.

Я выяснил причину, по которой клиент использовал URL-адрес HTTP вместо URL-адреса HTTPS (например, http://..., а не https://...), и наше приложение использует HSTS. Кажется, в IE 11 может быть ошибка, что при обновлении запроса до HTTPS из-за HSTS содержимое запроса теряется.

Если клиент исправил URL-адрес до https://..., содержимое было включено в запрос POST и решило проблему.

Я не исследовал, является ли это на самом деле ошибкой в ​​IE 11 на данном этапе.

0 голосов
/ 04 марта 2017

curl отправляет PUT/POST запросов с Content-Length: 0, если настроено использование прокси-сервера HTTP. Это хитрый способ преодолеть необходимую буферизацию в случае первого неавторизованного PUT/POST запроса к прокси. В случае GET/HEAD запросов curl просто повторяет запрос. Схема для PUT/POST выглядит так:

  1. Отправьте первый PUT/POST запрос с Content-Length, установленным в 0.

  2. Получить ответ. Код статуса HTTP 407 означает, что мы должны использовать прокси авторизации. Подготовьте заголовки для проверки подлинности прокси для отправки запроса.

  3. Повторно отправьте запрос с заполненными заголовками для аутентификации прокси и реальных данных в POST / PUT.

...