Плохой запрос. Подключение к сайтам через завиток на хосте и системе

У меня есть код cURL в php.

curl_setopt($ch, CURLOPT_URL, trim("http://stackoverflow.com/info/tagged/java")); 
curl_setopt($ch, CURLOPT_PORT, 80); //ignore explicit setting of port 80
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_HTTPHEADER, $v);
curl_setopt($ch, CURLOPT_VERBOSE, true);

Содержимое HTTPHEADER:

Proxy-Connection: Close
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=blabla
Connection: Close

Каждый из них - отдельные элементы в массиве $v.

Когда я загружаю файл на свой хост и запускаю код, то получаю:

400 Плохой запрос

Ваш браузер отправил неверный запрос.

Но когда я запускаю его в своей системе с помощью командной строки PHP, я получаю

< HTTP/1.1 200 OK
< Vary: Accept-Encoding
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Content-Encoding: gzip
< Date: Sat, 03 Mar 2012 21:50:17 GMT
< Connection: close
< Set-Cookie: buncha cokkies; path=/; HttpOnly
< Content-Length: 22151
< 
* Closing connection #0

.

Это не только в stackoverflow, это происходит, это происходит и на 4shared, но работает на google и других.

Спасибо за любую помощь.

Ответ 1

Это скорее комментарий, чем ответ: из вашего вопроса не понятно, что конкретно вызывает ошибку 400, и что особенно означает это или более конкретное: источник этого.

Это вывод вашего сервера? Это какая-то обратная связь (завиток), которую вы выводите с помощью script?

Чтобы лучше отлаживать вещи, я придумал немного другую конфигурацию, которую вы могли бы заинтересовать при использовании расширения curl. Существует хорошая функция под названием curl_setopt_array, которая позволяет вам установить сразу несколько параметров. Он вернет false, если один из вариантов завершится с ошибкой. Он позволяет настроить ваш запрос в полном объеме. Таким образом, вы можете легко вводить и заменять его с помощью второй (отладочной) конфигурации:

$curlDefault = array(
    CURLOPT_PORT => 80, //ignore explicit setting of port 80
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_FOLLOWLOCATION => TRUE,
    CURLOPT_ENCODING => '',
    CURLOPT_HTTPHEADER => array(
        'Proxy-Connection: Close',
        'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19',
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Encoding: gzip,deflate,sdch',
        'Accept-Language: en-US,en;q=0.8',
        'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3',
        'Cookie: __qca=blabla',
        'Connection: Close',
    ),
    CURLOPT_VERBOSE => TRUE, // TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.
);

$url = "http://stackoverflow.com/questions/tagged/java";
$handle = curl_init($url);
curl_setopt_array($handle, $curlDefault);
$html = curl_exec($handle);
curl_close($handle);

Это может помочь вам улучшить код и отладить вещи.

Кроме того, вы используете опцию CURLOPT_VERBOSE. Это добавит подробную информацию в STDERR, чтобы вы больше не могли ее отслеживать. Вместо этого вы можете добавить его к выходу, чтобы лучше понять, что происходит:

...
    CURLOPT_VERBOSE => TRUE, // TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.
    CURLOPT_STDERR => $verbose = fopen('php://temp', 'rw+'),
);

$url = "http://stackoverflow.com/questions/tagged/java";
$handle = curl_init($url);
curl_setopt_array($handle, $curlDefault);
$html = curl_exec($handle);
$urlEndpoint = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);
echo "Verbose information:\n<pre>", !rewind($verbose), htmlspecialchars(stream_get_contents($verbose)), "</pre>\n";
curl_close($handle);

Что дает следующий результат:

Verbose information:
* About to connect() to stackoverflow.com port 80 (#0)
*   Trying 64.34.119.12...
* connected
* Connected to stackoverflow.com (64.34.119.12) port 80 (#0)
> GET /questions/tagged/java HTTP/1.1
Host: stackoverflow.com
Proxy-Connection: Close
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=blabla
Connection: Close

< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Content-Encoding: gzip
< Vary: Accept-Encoding
< Date: Mon, 05 Mar 2012 17:33:11 GMT
< Connection: close
< Content-Length: 10537
< 
* Closing connection #0

Что должно предоставить вам информацию, необходимую для отслеживания вещей, если они связаны с запросом/завиванием. Затем вы можете легко изменить параметры и посмотреть, не изменилось ли это. Также сравните версию завитка, которую вы установили локально, с той, что была на сервере. Чтобы получить его, используйте curl_version:

$curlVersion = curl_version();
echo $curlVersion['version']; // e.g. 7.24.0

Надеюсь, это поможет вам отследить все.

Ответ 2

согласно http://php.net/manual/en/function.curl-setopt.php попробуйте установить CURLOPT_ENCODING на "gzip"

также я попытался бы избежать как можно большего количества строк заголовка, например, используйте CURLOPT_COOKIE вместо Cookie: __qca__=blabla или CURLOPT_USERAGENT

EDIT: кажется, что вы не используете массив (key = > value) для CURLOPT_HTTPHEADER, не так ли? в этом случае, используйте массив, и с другим материалом, я написал, с вами все будет в порядке. (как это делается, прочтите руководство: P)

надеюсь, что это поможет.