PHP HTTP POST терпит неудачу, когда данные cURL> 1024
Примечание: решение в конце
если я попытаюсь сделать HTTP-сообщение более 1024 символов, это не удастся. Почему? Вот минимальный пример:
получателя.на PHP:
<?php
if (strlen(file_get_contents('php://input')) > 1000
|| strlen($HTTP_RAW_POST_DATA) > 1000) {
echo "This was a triumph.";
}
?>
отправителя.на 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:"));
причина, кажется, в том, что любой пост более 1024 символ вызывает отправку HTTP-заголовка" Expect: 100-continue " и Lighttpd 1.4.* не поддерживает его. Я нашел билет на него:http://redmine.lighttpd.net/issues/show/1017
они говорят, что он работает в 1.5.
4 ответов
вы можете убедить бэкэнд curl PHP прекратить делать 100-continue-thing, установив явный заголовок запроса:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
таким образом, вы можете опубликовать запрос, сколько бы вы ни хотели, и curl не будет делать двухфазный пост.
Я сообщила об этом почти два года назад.
первые мысли...
страница руководства для curl_setopt говорит о CURLOPT_POSTFIELDS
"полные данные для публикации в HTTP" сообщение" операция. Чтобы опубликовать файл, добавьте filename С @ и используйте полный путь. Это может быть передано как строку в кодировке url, как 'para1=val1 & para2=val2&... или как массив с именем поля как ключ и данные поля как значение."
может ли быть, что ваша ценность рассматривается как urlencoded, и поэтому выглядит как большое длинное имя без значения. Что-то где-то решает сократить это имя.
может быть, вы могли бы изменить его на что-то вроде
$post_data = "data=".str_repeat('x', $char_count);
оказывается, это было слишком легко, и проблема была немного глубже. Итак, как отлаживать?
узнайте точно, что CURL отправляет на сервер
другой тактикой отладки может быть формулирование командной строки curl, которая достигает того же самого, и пусть он выведет данные HTTP-запроса, как он их делает.
тестирование сервера вручную
вы можете исключить сервер из уравнения, выполнив запрос вручную, например, telnetting на порт 80 на вашем сервере и отправив ему запрос >1024 chars
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.
Итак, по крайней мере, теперь вы знаете, что все это на стороне клиента, возможно, какой-то вариант завитка или настройка конфигурации где-то :(
финал Отвечай!
проблема заинтриговала меня, поэтому я копнул глубже
если вы используете 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:" Expect: "решил проблему для меня.
большое спасибо за эту ветку!
проверьте, включен ли патч Suhosin. По умолчанию он отключает данные POST после определенного количества индексов. Вы можете обойти его в suhosin config tho.