Примечание: решение в конце
Если я попытаюсь выполнить HTTP POST с более чем 1024 символами, это не сработает. Зачем? Вот минимальный пример:
recipient.php:
<?php if (strlen(file_get_contents('php://input')) > 1000 || strlen($HTTP_RAW_POST_DATA) > 1000) { echo "This was a triumph."; } ?>
sender.php:
<?php function try_to_post($char_count) { $url = 'http://gpx3quaa.joyent.us/test/recipient.php'; $post_data = str_repeat('x', $char_count); $c = curl_init(); curl_setopt_array($c, array( CURLOPT_URL => $url, CURLOPT_HEADER => false, CURLOPT_CONNECTTIMEOUT => 999, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $post_data ) ); $result = curl_exec($c); echo "{$result}\n"; curl_close($c); } for ($i=1020;$i<1030;$i++) { echo "Trying {$i} - "; try_to_post($i); } ?>
вывод:
Trying 1020 - This was a triumph. Trying 1021 - This was a triumph. Trying 1022 - This was a triumph. Trying 1023 - This was a triumph. Trying 1024 - This was a triumph. Trying 1025 - Trying 1026 - Trying 1027 - Trying 1028 - Trying 1029 -
конфигурация:
PHP Version 5.2.6 libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3 libidn/1.8 lighttpd-1.4.19
Решение
Добавьте следующий параметр для cURL:
curl_setopt($ch,CURLOPT_HTTPHEADER,array("Expect:"));
Причина в том, что любой POST более 1024 символов вызывает отправку HTTP-заголовка «Ожидание: 100-продолжить», а Lighttpd 1.4. * Не поддерживает его. Я нашел для него билет: http://redmine.lighttpd.net/issues/show/1017
Говорят, что это работает в 1.5.
Вы можете убедить, что PHP-реверс завершает работу с 100-продолжением, устанавливая явный заголовок запроса:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
Таким образом, вы можете отправить запрос, сколько бы вы ни пожелали, и завиток не будет выполнять двухэтапный пост.
Об этом почти два года назад сообщалось в блоге .
На странице руководства curl_setopt говорится о CURLOPT_POSTFIELDS
«Полные данные для публикации в HTTP-сообщении« POST ». Чтобы опубликовать файл, добавьте имя файла с помощью @ и используйте полный путь. Это может быть передано как строка с urlencoded, такая как« para1 = val1 & para2 = val2 & … » или как массив с именем поля в качестве ключа и данными поля как значение. "
Может быть, ваша ценность обрабатывается так, как если бы она была указана на urlencoded и, таким образом, выглядела как длинное длинное имя без какой-либо ценности. Что-то где-то решает усечь это имя.
Может быть, вы можете изменить его на что-то вроде
$post_data = "data=".str_repeat('x', $char_count);
Оказывается, это было слишком легко, и проблема была немного глубже. Итак, как отлаживать?
Другая тактика отладки может заключаться в том, чтобы сформулировать командную строку curl, которая достигает того же самого, и вывести данные HTTP-запроса по мере их создания.
Вы можете исключить сервер из уравнения, выполнив запрос вручную, например, telnetting на порт 80 на вашем сервере и отправив ему запрос> 1024 символов
POST /test/recipient.php HTTP/1.0 Host: gpx3quaa.joyent.us Content-Length:1028 xxxxx(I put 1028 chars here, no point copying them all here!)
Я получил этот ответ
HTTP/1.0 200 OK Connection: close Content-type: text/html; charset=UTF-8 Content-Length: 19 Date: Tue, 20 Jan 2009 21:35:16 GMT Server: lighttpd/1.4.19 This was a triumph.Connection closed by foreign host.
Итак, по крайней мере, теперь вы знаете, что все это на стороне клиента, возможно, где-то параметр CURL или настройка конфигурации 🙁
Проблема заинтриговала меня, поэтому я вырыл глубже
Если вы используете CURLOPT_VERBOSE=>true
, вы увидите, что CURL отправляет дополнительный заголовок на более крупные сообщения: Expect: 100-Continue
. Казалось бы, вашему серверу lighttpd это не понравится.
Вы можете остановить CURL от этого, заставив его использовать HTTP / 1.0 с CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_0
в вашем массиве параметров curl_setopt.
У меня была аналогичная проблема с сервером IIS с использованием SSL v3.
Я продолжал получать следующую ошибку cURL, когда CURLOPT_POSTFIELDS было больше 1024:
52 - SSL read: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number, errno 0
Добавление CURLOPT_HTTPHEADER: «Ожидайте:» решила проблему для меня.
Большое вам спасибо за эту тему!
Проверьте, включен ли патч Suhosin. По умолчанию он отключает данные POST после определенного количества индексов. Вы можете обойти его в Suhosin config tho.