PHP HTTP POST завершается ошибкой, когда данные cURL> 1024 - PullRequest
11 голосов
/ 21 января 2009

Примечание: решение в конце

Если я попытаюсь выполнить 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-заголовка «Expect: 100-continue», а Lighttpd 1.4. * Не поддерживает его. Я нашел билет на него: http://redmine.lighttpd.net/issues/show/1017

Говорят, работает в 1.5.

Ответы [ 4 ]

22 голосов
/ 21 января 2009

Вы можете убедить бэкэнд PHP в curl прекратить выполнение 100-продолжение, установив явный заголовок запроса:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

Таким образом, вы можете опубликовать запрос так долго, как захотите, и curl не будет выполнять двухфазную публикацию.

Я писал об этом почти два года назад.

3 голосов
/ 21 января 2009

Первые мысли ...

Страница руководства для curl_setopt говорит о CURLOPT_POSTFIELDS

"Полные данные для публикации в HTTP" POST " операция. Чтобы опубликовать файл, добавьте имя файла с @ и использовать полный путь. Это может быть передано как urlencoded строка 'para1 = val1 & para2 = val2 & ...' или как массив с именем поля в качестве ключа и данные поля как значение. "

Может ли быть так, что ваше значение обрабатывается так, как если бы оно было urlencoded, и, таким образом, выглядит как большое длинное имя без значения. Что-то где-то решает усечь это имя.

Может быть, вы могли бы изменить его на что-то вроде

$post_data = "data=".str_repeat('x', $char_count);

Оказывается, это было слишком легко, и проблема была немного глубже. Итак, как отлаживать?

Узнайте, что именно CURL отправляет на сервер

Другая тактика отладки может состоять в том, чтобы сформулировать командную строку 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.

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

Проверьте, включен ли патч Suhosin. По умолчанию он обрезает данные POST после определенного числа индексов. Вы можете обойти это в конфигурации Suhosin tho.

0 голосов
/ 05 мая 2009

У меня была похожая проблема с сервером 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:» решило проблему для меня.

Большое спасибо за эту тему!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...