Рейтинг:0

Ошибка POST-запроса HTTPS в связи с Content-Length

флаг iq

Приложение PHP отправляет XML-данные с помощью curl; ничего особенного, вывод выглядит так (c/p, но идентификаторы и пароли изменены):

Хост: иностранный.хост.пример
Авторизация: Базовая dGVzdDpnZWhlaW0=
User-Agent: HTTP-коннектор нашего хоста/1.0
Принимать: */*
Реферер: https://our.host.example/
Тип содержимого: текст/xml
Длина содержимого: 9218
Ожидать: 100-продолжить

[9218 байт данных XML]

Это делается на паре исходных хостов S1...Sn и отправляется на пару целевых хостов T1...Tn. Неделю назад хост S1 был обновлен с Debian/buster до Debian/bullseye; генерирующее программное обеспечение PHP также было обновлено, но я не знаю о каких-либо изменениях в этой области (и сгенерированные запросы выглядят одинаково). Именно после этого обновления два (не связанных) целевых хоста T1 и T2 отказываются от наших запросов с кодом ответа 400. Все остальные целевые хосты работают нормально, а T1/T2 работают нормально, если подключены с других исходных хостов (со старой версией).

Вывод: вина на нашей стороне. Но где?

Примечание: удаление заголовка Expect ничего не меняет.

Дополнительная информация: в то время как T1 отвечает только с кодом ответа 400, T2 вежлив и включает сообщение о состоянии, например:

[наш.ip.адрес]:60760 имеет неполный запрос: расчетная длина 3994 байт(ов), получено 3899 байт(ов)

К сожалению, этой подсказки недостаточно, чтобы просветить меня (да и у контактов там тоже недостаточно знаний для этого), но она привела меня к следующему

Обходной путь: если я подавляю заголовок Content-Length, передача работает

Это лучше, чем ничего, но не удовлетворяет — я хочу, чтобы проблема была решена; поэтому я дважды и трижды проверил число в заголовке Content-Length (поскольку это единственный возможный источник ошибки, о котором я могу думать до сих пор); вроде все в порядке, и точно такой же расчет используется на хостах S2...Sn, которые все еще работают. И: длина контента плюс оценочный заголовок (это, конечно, будет немного отличаться из-за другого хоста, авторизации и реферера) — это не оценочная длина и не полученная длина, а где-то посередине. На данный момент в ответах указаны следующие цифры:

Оцененный Получили Разница
4322 4228 94
3972 3877 95
3994 3899 95
6928 6768 160

К сожалению, это не постоянно и ни о чем не говорит.

Я установил пару тегов, потому что Apache (2.4.52), OpenSSL (1.1.1k), curl (7.74.0) и PHP (7.4.25) были обновлены вместе с сервером, хотя я не вижу никакого возможного влияния. Но у меня нет других идей, поэтому я не хочу исключать это.

Любые идеи приветствуются.

флаг jp
Используйте tcpdump или прокси-сервер для захвата исходящего запроса и убедитесь, что у вас есть правильная длина содержимого на проводе.
флаг iq
Это сводило меня с ума: с помощью mitmproxy я могу перехватывать звонки на один из наших собственных сайтов — все в порядке. Если я попытаюсь связаться с T1 или T2, запрос __зависнет__, пока mitmproxy выполняет рукопожатие с удаленным хостом; Я вообще не вижу заголовков. Как только я удаляю Content-Length, все работает как положено.
флаг iq
Но я сейчас заглянул в репозиторий: заголовок Content-Length установлен с момента появления софта в 2006 году. Скорее всего что-то давно изменилось в фоне (cURL), как будто я его просто опускаю, cURL устанавливает в любом случае правильный заголовок. Поэтому, хотя я до сих пор не понимаю, что здесь происходит, я прекращаю дальнейшие исследования на этом этапе.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.