Как получить заголовки ответа
В предыдущем примере мы научились посылать заголовки. Самый правильный способ принять заголовки:
$ch = curl_init(); $headers = []; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // ... остальные опции // this function is called by curl for each header received curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$response_headers) { $len = strlen($header); $header = explode(':', $header, 2); if (count($header) < 2) { // ignore invalid headers return $len; } $headers))][] = trim($header); return $len; } ); $data = curl_exec($ch); print_r($response_headers); // выводим заголовки ответа
Иногда можно встретить другой вариант получения заголовков ответа. К сожалению, они не совсем правильные и могут работать некорректно в некоторых случаях.
Рассмотрим такой пример:
$ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); // ... $response = curl_exec($ch); // Then, after your curl_exec call: $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size);
Мы сначала определяем размер заголовка, с помощью CURLINFO_HEADER_SIZE затем вырезаем его из ответа. К сожалению, это может не срабатывать, когда используется прокси или в некоторых случаях редиректа.
Авторизация с помощью cURL
HTTP Авторизация
Чтобы с помощью cURL авторизироваться на сайте, который использует Basic HTTP-аутентификацию нужно установить опцию CURLOPT_USERPWD, в которой будет наш логин и пароль.
Пример:
$login = 'test_login'; // наш логин $password = 'test_password'; // наш пароль $url = 'https://phpstack.ru/'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_USERPWD, "$login:$password"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); curl_close($ch);
OAuth авторизация
$url = 'https://phpstack.ru/'; $oauthToken = 'Bearer dsfgdsfgdsfgdsfgdsfg'; // наш токен $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: $oauthToken")); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $html = curl_exec($ch); curl_close($ch);
Авторизация через форму
Давайте применим полученные нами знания и авторизируемся на каком-нибудь сайте. Для этого нужно посмотреть куда форма отправляет данные и отправить туда то же самое.
Допустим на сайте есть такая форма:
<html> <body> <form method = "POST" action="https://phpstack.ru/admin/' > <input name="login" type="text"> <input name="password" type="text"> <input type="submit" name="submit" value="Отправить" > </form> </body> </html>
Тогда наш cURL запрос должен быть сформирован так:
$url = 'http://phpstack.ru/admin/'; // url, на который отправляется запрос $postData = [ // поля нашего запроса 'login' => 'our_login', // наш логин 'password' => 'our_password', // наш пароль ]; $cookieFile = __DIR__ . '/cookie.txt'; // притворяемся браузером $headers = [ 'Connection: keep-alive', 'Upgrade-Insecure-Requests: 1', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding: gzip, deflate', 'Accept-Language: ru,en-US;q=0.9,en;q=0.8', ]; $post_data = http_build_query($post_data); $curl = curl_init(); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_VERBOSE, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); curl_setopt($curl, CURLOPT_COOKIEFILE, $cookieFile); curl_setopt($curl, CURLOPT_COOKIEJAR, $cookieFile); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_POST, true); // true $result = curl_exec($curl);
В $result у нас ответ сервера, мы можем проверить, что на странице находится сообщение об успешной авторизации и дальше гулять по личному кабинету сайта. Да, кстати, не используйте эти знания в противоправных целях.
Отправка файлов
Для того, чтобы отправить файлы на сервер, мы просто заполняем поля POST запроса, указывая там специальный класс CURLFile. На сервере вы можете получить отправленные файлы, при помощи суперглобального массива $_FILES.
$url = 'https://phpstack.ru/'; $postFields = [ 'photo1' => new \CURLFile( __DIR__ . '/img1.jpg' ), 'photo2' => new \CURLFile( __DIR__ . '/img2.jpg' ), ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $html = curl_exec($ch); curl_close($ch);
Загрузка файлов методом POST
Для HTTP запроса типа POST существует два варианта передачи полей из HTML форм, а именно, используя алгоритм и . Алгоритм первого типа создавался давным-давно, когда в языке HTML еще не предусматривали возможность передачи файлов через HTML формы.
Со временем возникла необходимость через формы отсылать еще и файлы. Тогда консорциум W3C взялся за доработку формата POST запроса, в результате чего появился документ RFC 1867. Форма, которая позволяет пользователю загрузить файл, используя алгоритм , выглядит примерно так:
<form action="/upload.php" method="POST" enctype="multipart/form-data"> <input type="file" name="upload"> <input type="submit" name="submit" value="OK"> </form>
Чтобы отправить на сервер данные такой формы:
> curl -F [email protected] -F submit=OK http://www.example.com/upload.php
Скрипт , который принимает данные формы:
<?php print_r($_POST); print_r($_FILES); move_uploaded_file($_FILES'upload''tmp_name', 'image.jpg');
Ответ сервера:
Array ( => OK ) Array ( => Array ( => image.jpg => image/jpeg => D:\work\temp\phpB02F.tmp => 0 => 2897 ) )
Technique #2: From a PHP script
I’ve written on debugging cURL and PHP at Kettle.io Blog. Let’s say you have to send a dynamic header with the request, like a JWT authorization token. It’s not impossible to that from the command line, but it’s easier using programming. For those cases, I use the cURL PHP extension. Check out the script below.
$url = 'http://google.com'; $headers = [ 'Accept' => 'application/json', ]; /* * We're going to use the output buffer to store the debug info. */ ob_start(); $out = fopen('php://output', 'w'); $handler = curl_init($url); /* * Here we set the library verbosity and redirect the error output to the * output buffer. */ curl_setopt($handler, CURLOPT_VERBOSE, true); curl_setopt($handler, CURLOPT_STDERR, $out); $requestHeaders = []; foreach ($headers as $k => $v) { $requestHeaders[] = $k . ': ' . $v; } curl_setopt($handler, CURLOPT_HTTPHEADER, $requestHeaders); curl_setopt($handler, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($handler); fclose($out); /* * Joining debug info and response body. */ $data = ob_get_clean(); $data .= PHP_EOL . $response . PHP_EOL; echo $data;
Now, you can customize this code to add some dynamic data to a header or any other request part. After doing that, run it using the PHP program from the command line:
$ php curldebug.php
P.S.: I’m assuming that you saved the script as .
As we did with the curl program, it’s possible to output everything to a file. Just append the to the call.
Отправка cURL запроса PHP
Формирование cURL запроса состоит из четырех этапов:
- Инициализация
- Указание параметров
- Выполнение команды и получение результата
- Освобождение памяти
Итак, как это должно выглядеть в коде:
// 1. Инициализация $ch = curl_init(); // 2. Указание параметров curl_setopt($ch, CURLOPT_URL, "https://asgeto.ru"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); // 3. Выполнение команды и получение результата $output = curl_exec($ch); // В случае возникновения ошибки выводит её в документ if ($output === FALSE) { echo "cURL Error: " . curl_error($ch); // можно заменить на логирование в файл при желании } // 4. Освобождение памяти curl_close($ch);
Скачивание больших файлов с помощью cURL
Для того, чтобы скачать большой файл пригодится этот способ:
$url = 'https://example.com/big_file.zip'; // откуда скачиваем файл $path = __DIR__ . '/big_file.zip'; // куда сохраняем файл $fp = fopen($path, 'w'); $ch = curl_init($url); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $data = curl_exec($ch); curl_close($ch); fclose($fp);
Обратите внимание, если вы будете использовать file_get_contents для скачивания файлов, то файл сначала загружается в оперативную память, а потом сохраняется на диск. Поэтому если файл действительно большой, то скорее всего вашему серверу не хватит памяти
Также к памяти будет требователен следующий код:
$ch = curl_init('https://example.ru/big_file.zip'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $data = curl_exec($ch); curl_close($ch); file_put_contents(__DIR__ . '/big_file.zip', $data);
Здесь мы скачиваем файл при помощи cURL в оперативную память, а затем сохраняем его на диск. Не смотря на то, что этот способ не годится для скачивания больших файлов, с помощью него можно вполне сохранить простую веб страницу.
Пример работы с библиотекой
Я считаю, что после того, как некоторые общие моменты уже ясны и вроде бы все понятно, то самое время переходить к практике и на примере уже оттачивать свое мастерство. Лично у меня всегда сразу руки чешутся все попробовать на практике
Раз уж cURL так хорош для парсеров, то рассмотрим функцию получения кода страницы по ее адресу. При этом на выходе получим массив с заголовком, содержимым страницы и даже коды ошибок, если что-то пойдет не так.
Входные параметры:url — адрес страницы или сайта.
Значения выходных параметров (массив с тремя элементами):header — если что-то пошло не так, то тут будет код ошибки.header — здесь при этом будет текст ошибки.header — собственно сама страница\файл\картинка и т.д.
Используем функцию, например, так:
$result = get_web_page( "https://ya.ru" ); if (($result != 0 )||($result != 200)) { echo $result; } else { $page = $result; echo $page; }
Все должно пройти без ошибок и вы получите код страницы в переменной $page. Если же попробовать получить несуществующую страницу , то получим ошибку:
Could not resolve host: yaaaaaaaaaaaa.ru; Host not found
Все обрабатывается корректно и красиво
Дальше с кодом страницы можно делать все что угодно, например, парсить регулярками. Но это все в следующих уроках, а пока что остановимся на этом.
Часто используемые функции CURL и константы
- curl_init — Инициализирует сеанс;
- curl_close — Завершает сеанс;
- curl_exec — Выполняет запрос;
- curl_errno — Возвращает код ошибки;
- curl_setopt — Устанавливает параметр для сеанса, например:
- CURLOPT_HEADER – значение 1 означает, что необходимо вернуть заголовки;
- CURLOPT_INFILESIZE — параметр для указания ожидаемого размера файла;
- CURLOPT_VERBOSE — значение 1 означает что CURL будет выводить подробные сообщения о всех производимых операциях;
- CURLOPT_NOPROGRESS – отключение индикатора прогресса операции, значение 1;
- CURLOPT_NOBODY – если Вам не нужен документ, а нужны только заголовки, то поставьте значение 1;
- CURLOPT_UPLOAD — для закачки файла на сервер;
- CURLOPT_POST – выполнить запрос методом POST;
- CURLOPT_FTPLISTONLY — получение списка файлов в директории FTP сервера, значение 1;
- CURLOPT_PUT — выполнить запрос методом PUT, значение 1;
- CURLOPT_RETURNTRANSFER — возвратить результат, не выводя в браузер, значение 1;
- CURLOPT_TIMEOUT – максимальное время выполнения в секундах;
- CURLOPT_URL – указание адреса для обращения;
- CURLOPT_USERPWD — строка с именем пользователя и паролем в виде :;
- CURLOPT_POSTFIELDS – данные для POST запроса;
- CURLOPT_REFERER — задает значение HTTP заголовка «Referer: »;
- CURLOPT_USERAGENT — задает значение HTTP заголовка «User-Agent: »;
- CURLOPT_COOKIE — содержимое заголовка «Cookie: », который будет отправлен с HTTP запросом;
- CURLOPT_SSLCERT- имя файла с сертификатом в формате PEM;
- CURLOPT_SSL_VERIFYPEER – значение 0, для того чтобы запретить проверку сертификата удаленного сервера (по умолчанию 1);
- CURLOPT_SSLCERTPASSWD — пароль к файлу сертификата.
- curl_getinfo — Возвращает информацию об операции, вторым параметром может выступать константа для указания, что именно нужно показать, например:
- CURLINFO_EFFECTIVE_URL — последний использованный URL;
- CURLINFO_HTTP_CODE — последний полученный код HTTP;
- CURLINFO_FILETIME — дата модификации загруженного документа;
- CURLINFO_TOTAL_TIME — время выполнения операции в секундах;
- CURLINFO_NAMELOOKUP_TIME — время разрешения имени сервера в секундах;
- CURLINFO_CONNECT_TIME — время, затраченное на установку соединения, в секундах;
- CURLINFO_PRETRANSFER_TIME — время, прошедшее от начала операции до готовности к фактической передаче данных, в секундах;
- CURLINFO_STARTTRANSFER_TIME — время, прошедшее от начала операции до момента передачи первого байта данных, в секундах;
- CURLINFO_REDIRECT_TIME — время, затраченное на перенаправление, в секундах;
- CURLINFO_SIZE_UPLOAD — количество байт при закачке;
- CURLINFO_SIZE_DOWNLOAD — количество байт при загрузке;
- CURLINFO_SPEED_DOWNLOAD — средняя скорость закачки;
- CURLINFO_SPEED_UPLOAD — средняя скорость загрузки;
- CURLINFO_HEADER_SIZE — суммарный размер всех полученных заголовков;
- CURLINFO_REQUEST_SIZE — суммарный размер всех отправленных запросов;
- CURLINFO_SSL_VERIFYRESULT — результат проверки SSL сертификата, запрошенной с помощью установки параметра CURLOPT_SSL_VERIFYPEER;
- CURLINFO_CONTENT_LENGTH_DOWNLOAD — размер загруженного документа, прочитанный из заголовка Content-Length;
- CURLINFO_CONTENT_LENGTH_UPLOAD — размер закачиваемых данных;
- CURLINFO_CONTENT_TYPE — содержимое полученного заголовка Content-type, или NULL в случае, когда этот заголовок не был получен.
Подробнее о функциях CURL и константах к ним можете посмотреть на официальном сайте PHP — php.net
На этом все, для начинающих я думаю достаточно Удачи!
Protocol options
CURLOPT_TRANSFERTEXT
Use text transfer. See CURLOPT_TRANSFERTEXT
CURLOPT_PROXY_TRANSFER_MODE
Add transfer mode to URL over proxy. See CURLOPT_PROXY_TRANSFER_MODE
CURLOPT_CRLF
Convert newlines. See CURLOPT_CRLF
CURLOPT_RANGE
Range requests. See CURLOPT_RANGE
CURLOPT_RESUME_FROM
Resume a transfer. See CURLOPT_RESUME_FROM
CURLOPT_RESUME_FROM_LARGE
Resume a transfer. See CURLOPT_RESUME_FROM_LARGE
CURLOPT_CURLU
Set URL to work on with CURLU *. See CURLOPT_CURLU
CURLOPT_CUSTOMREQUEST
Custom request/method. See CURLOPT_CUSTOMREQUEST
CURLOPT_FILETIME
Request file modification date and time. See CURLOPT_FILETIME
CURLOPT_DIRLISTONLY
List only. See CURLOPT_DIRLISTONLY
CURLOPT_NOBODY
Do not get the body contents. See CURLOPT_NOBODY
CURLOPT_INFILESIZE
Size of file to send. CURLOPT_INFILESIZE
CURLOPT_INFILESIZE_LARGE
Size of file to send. CURLOPT_INFILESIZE_LARGE
CURLOPT_UPLOAD
Upload data. See CURLOPT_UPLOAD
CURLOPT_UPLOAD_BUFFERSIZE
Set upload buffer size. See CURLOPT_UPLOAD_BUFFERSIZE
CURLOPT_MIMEPOST
Post/send MIME data. See CURLOPT_MIMEPOST
CURLOPT_MIME_OPTIONS
Set MIME option flags. See CURLOPT_MIME_OPTIONS
CURLOPT_MAXFILESIZE
Maximum file size to get. See CURLOPT_MAXFILESIZE
CURLOPT_MAXFILESIZE_LARGE
Maximum file size to get. See CURLOPT_MAXFILESIZE_LARGE
CURLOPT_TIMECONDITION
Make a time conditional request. See CURLOPT_TIMECONDITION
CURLOPT_TIMEVALUE
Time value for the time conditional request. See CURLOPT_TIMEVALUE
CURLOPT_TIMEVALUE_LARGE
Time value for the time conditional request. See CURLOPT_TIMEVALUE_LARGE
Иммитация браузера с помощью cURL
Иногда сайт, к которому мы обращаемся может фильтровать запросы, защищаясь от парсинга. Если для этого используются упрощенные способы защиты, например проверка User-Agent, то мы можем легко притвориться, что являемся реальным польователем, который взаимодействует с сайтом через браузер, мы можем послать заголовки и cookie, которые обычно посылает браузер.
В данном примере установлены заголовки, которые посылает Chrome.
$url = 'https://phpstack.ru/'; $headers = [ 'Connection: keep-alive', 'Upgrade-Insecure-Requests: 1', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding: gzip, deflate', 'Accept-Language: ru,en-US;q=0.9,en;q=0.8', ]; $cookieFile = __DIR__ . '/cookie.txt'; $curl = curl_init(); // создаем экземпляр curl curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_VERBOSE, 1); curl_setopt($curl, CURLOPT_COOKIEFILE, $cookieFile); curl_setopt($curl, CURLOPT_COOKIEJAR, $cookieFile); curl_setopt($curl, CURLOPT_POST, false); // curl_setopt($curl, CURLOPT_URL, $url); $result = curl_exec($curl);
В простых ситуациях этого хватает. Но если используется защита при помощи javascript или что-то более продвинутое, то здесь cURL бессилен, и следует использовать либо BAS либо Zennoposter. Либо если вы хотите попытать счастье с PHP, то Selenium.
Не используйте эти знания в противоправных целях.
Ответ 3
Curl имеет встроенную опцию для этого, называемую CURLOPT_HEADERFUNCTION. Значение этой опции должно быть именем функции обратного вызова. Curl передаст заголовок (и только заголовок!) этой функции обратного вызова построчно (таким образом, функция будет вызываться для каждой строки заголовка, начиная с верхней части раздела заголовка). Затем ваша функция обратного вызова может делать с ним все что угодно (и должна вернуть количество байт данной строки). Вот проверенный рабочий код:
function HandleHeaderLine( $curl, $header_line ) {
echo «<br>YEAH: «.$header_line; // или сделать что угодно
return strlen($header_line);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, «http://www.google.com»);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, «HandleHeaderLine»);
$body = curl_exec($ch);
Вышеописанное работает со всем, с различными протоколами и прокси, и вам не нужно беспокоиться о размере заголовка или устанавливать множество различных опций curl.
P. S.: Чтобы обработать строки заголовка с помощью объектного метода, сделайте следующее:
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$object, ‘methodName’))
Команда curl
Перед тем как перейти к описанию того как может использоваться команда curl linux, давайте разберем саму утилиту и ее основные опции, которые нам понадобятся. Синтаксис утилиты очень прост:
$ curlопции ссылка
Теперь рассмотрим основные опции:
- -# – отображать простой прогресс-бар во время загрузки;
- -0 – использовать протокол http 1.0;
- -1 – использовать протокол шифрования tlsv1;
- -2 – использовать sslv2;
- -3 – использовать sslv3;
- -4 – использовать ipv4;
- -6 – использовать ipv6;
- -A – указать свой USER_AGENT;
- -b – сохранить Cookie в файл;
- -c – отправить Cookie на сервер из файла;
- -C – продолжить загрузку файла с места разрыва или указанного смещения;
- -m – максимальное время ожидания ответа от сервера;
- -d – отправить данные методом POST;
- -D – сохранить заголовки, возвращенные сервером в файл;
- -e – задать поле Referer-uri, указывает с какого сайта пришел пользователь;
- -E – использовать внешний сертификат SSL;
- -f – не выводить сообщения об ошибках;
- -F – отправить данные в виде формы;
- -G – если эта опция включена, то все данные, указанные в опции -d будут передаваться методом GET;
- -H – передать заголовки на сервер;
- -I – получать только HTTP заголовок, а все содержимое страницы игнорировать;
- -j – прочитать и отправить cookie из файла;
- -J – удалить заголовок из запроса;
- -L – принимать и обрабатывать перенаправления;
- -s – максимальное количество перенаправлений с помощью Location;
- -o – выводить контент страницы в файл;
- -O – сохранять контент в файл с именем страницы или файла на сервере;
- -p – использовать прокси;
- –proto – указать протокол, который нужно использовать;
- -R – сохранять время последнего изменения удаленного файла;
- -s – выводить минимум информации об ошибках;
- -S – выводить сообщения об ошибках;
- -T – загрузить файл на сервер;
- -v – максимально подробный вывод;
- -y – минимальная скорость загрузки;
- -Y – максимальная скорость загрузки;
- -z – скачать файл, только если он был модифицирован позже указанного времени;
- -V – вывести версию.
Это далеко не все параметры curl linux, но здесь перечислено все основное, что вам придется использовать.
Как узнать, работает ли у вас cURL?
Создайте php файл и скопируйте туда:
<?php print_r (curl_version()); ?>
Откройте его с сервера. Если на выходе что-то вроде:
Array ( => 468736 => 3 => 3997 => 0 => 7.39.0 => x86_64-pc-win32 => OpenSSL/1.0.1j => 1.2.7.3 => Array ( => dict => file => ftp => ftps => gopher => http => https => imap => imaps => ldap => pop3 => pop3s => rtsp => scp => sftp => smtp => smtps => telnet => tftp ) )
Значит с cURL всё в порядке, если вместо этого ошибка PHP, значит проблема существует.
Во-первых, конечно же проверьте файл php.ini, найдите там строчку
extension=php_curl.dll
И убедитесь, что перед ней не стоит точка с запятой.
Если всё так, а cURL не работает, то можно провести ещё один тест, для подтверждения необычности ситуации. Создайте ещё один php файл с содержанием:
<?php phpinfo ();?>
Через поиск в браузере найдите cURL, если совпадение всего одно, значит модуль cURL не загружен:
При этом и Apache и PHP работают как обычно.
Решений три:
- Способ первый (не кошерный). Если у вас PHP 5.6.*, то возьмите версию PHP 5.6.0, оттуда возьмите старый файл php_curl.dll и замените его вместо вашего нового из версии, например, PHP 5.6.4. Для тех, у кого PHP 5.5.17 и выше, нужно взять этот же файл из PHP 5.5.16 и также его заменить. Проблема здесь одна — найти эти старые версии. Можно, конечно, покавыряться в http://windows.php.net/downloads/snaps/php-5.6, но лично я там не нашёл того, что мне нужно. Да и само решение какое-то не совсем кошерное.
- Способ второй (очень быстрый, но тоже не кошерный). Из каталога PHP скопировать файл libssh2.dll в каталог Apache24bin и перезапустить Apache.
- Способ третий (кошерный — кошерные люди аплодируют стоя). Нужно добавить вашу PHP директорию в PATH. Как это сделать очень хорошо расписано в .
Проверяем:
Вуаля, секция cURL на месте.
Почему так? Откуда взялась эта проблема? Ответа на этот вопрос нет, хотя уже описан механизм её возникновения.
Проблема связана, вроде, с тем, что 5.6.1 должен был выпущен с обновлённым libcurl 7.38.0. Но это доподлинно не известно, авторы PHP кивают на Apache, мол это там какие-то баги.
Механизм возникновения проблемы: если в системную PATH не включён каталог PHP, то когда служба Apache запускается, она не способна найти новый dll (libssh2.dll), который является зависимостью для php_curl.
Соответствующие баг репорты:
Ответ 2
Хотя этот вопрос довольно стандартный, и предыдущий ответ действителен, я нахожу его немного неудобным, потому что содержимое HTTP-ответа (HTML, XML, JSON, двоичный или любой другой) становится смешанным с заголовками. Я нашел другую альтернативу. CURL предоставляет опцию (CURLOPT_HEADERFUNCTION) для установки обратного вызова, который будет вызываться для каждой строки заголовка ответа. Функция будет получать объект curl и строку заголовка. Вы можете использовать код, подобный этому:
$cookies = Array();
$ch = curl_init(‘http://www.google.com/’);
// Запросить обратный вызов.
curl_setopt($ch, CURLOPT_HEADERFUNCTION, «curlResponseHeaderCallback»);
$result = curl_exec($ch);
var_dump($cookies);
function curlResponseHeaderCallback($ch, $headerLine) {
global $cookies;
if (preg_match(‘/^Set-Cookie:\s*(*)/mi’, $headerLine, $cookie) == 1)
$cookies[] = $cookie;
return strlen($headerLine); // Needed by curl
}
Это решение имеет недостаток в использовании глобальной переменной, но я думаю, что это не проблема для коротких скриптов. И вы всегда можете использовать статические методы и атрибуты, если curl оборачивается в класс.
POST запрос с помощью CURL
Давайте напишем наш первый скрипт, который отправит данные методом POST на какую-нибудь страницу и посмотрит, что отобразилось на этой странице.
Сначала нам нужен файл, который бы принял наши данные и что-то вывел на страницу. Я расположил его по адресу https://intop24.ru/demo/curl/post.php. В нем содержится следующий код:
if (isset($_POST) && sizeof($_POST) > 0) { print_r($_POST); }
Теперь попробуем передать туда какие-то данные:
$url = “https://intop24.ru/demo/curl/post.php”; $post_data = array ( “foo” => “bar”, “query” => “Nettuts”, “action” => “Submit” ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Указываем, что у нас POST запрос curl_setopt($ch, CURLOPT_POST, 1); // Добавляем переменные curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($ch); curl_close($ch); echo $output;
Результат можно посмотреть здесь: curl_post.php
Как пользоваться curl?
Мы рассмотрели все, что касается теории работы с утилитой curl, теперь пришло время перейти к практике, и рассмотреть примеры команды curl.
Загрузка файлов
Самая частая задача — это загрузка файлов linux. Скачать файл очень просто. Для этого достаточно передать утилите в параметрах имя файла или html страницы:
Но тут вас ждет одна неожиданность, все содержимое файла будет отправлено на стандартный вывод. Чтобы записать его в какой-либо файл используйте:
А если вы хотите, чтобы полученный файл назывался так же, как и файл на сервере, используйте опцию -O:
Если загрузка была неожиданно прервана, вы можете ее возобновить:
Если нужно, одной командой можно скачать несколько файлов:
Еще одна вещь, которая может быть полезной администратору — это загрузка файла, только если он был изменен:
Данная команда скачает файл, только если он был изменен после 21 декабря 2017.
Ограничение скорости
Вы можете ограничить скорость загрузки до необходимого предела, чтобы не перегружать сеть с помощью опции -Y:
Здесь нужно указать количество килобайт в секунду, которые можно загружать. Также вы можете разорвать соединение если скорости недостаточно, для этого используйте опцию -Y:
Передача файлов
Загрузка файлов, это достаточно просто, но утилита позволяет выполнять и другие действия, например, отправку файлов на ftp сервер. Для этого существует опция -T:
Или проверим отправку файла по HTTP, для этого существует специальный сервис:
В ответе утилита сообщит где вы можете найти загруженный файл.
Отправка данных POST
Вы можете отправлять не только файлы, но и любые данные методом POST. Напомню, что этот метод используется для отправки данных различных форм. Для отправки такого запроса используйте опцию -d. Для тестирования будем пользоваться тем же сервисом:
Если вас не устраивает такой вариант отправки, вы можете сделать вид, что отправили форму. Для этого есть опция -F:
Здесь мы передаем формой поле password, с типом обычный текст, точно так же вы можете передать несколько параметров.
Передача и прием куки
Куки или Cookie используются сайтами для хранения некой информации на стороне пользователя. Это может быть необходимо, например, для аутентификации. Вы можете принимать и передавать Cookie с помощью curl. Чтобы сохранить полученные Cookie в файл используйте опцию -c:
Затем можно отправить cookie curl обратно:
Передача и анализ заголовков
Не всегда нам обязательно нужно содержимое страницы. Иногда могут быть интересны только заголовки. Чтобы вывести только их есть опция -I:
А опция -H позволяет отправить нужный заголовок или несколько на сервер, например, можно передать заголовок If-Modified-Since чтобы страница возвращалась только если она была изменена:
Аутентификация curl
Если на сервере требуется аутентификация одного из распространенных типов, например, HTTP Basic или FTP, то curl очень просто может справиться с такой задачей. Для указания данных аутентификации просто укажите их через двоеточие в опции -u:
Точно так же будет выполняться аутентификация на серверах HTTP.
Использование прокси
Если вам нужно использовать прокси сервер для загрузки файлов, то это тоже очень просто. Достаточно задать адрес прокси сервера в опции -x:
Ftp options
CURLOPT_FTPPORT
Use active FTP. See CURLOPT_FTPPORT
CURLOPT_QUOTE
Commands to run before transfer. See CURLOPT_QUOTE
CURLOPT_POSTQUOTE
Commands to run after transfer. See CURLOPT_POSTQUOTE
CURLOPT_PREQUOTE
Commands to run just before transfer. See CURLOPT_PREQUOTE
CURLOPT_APPEND
Append to remote file. See CURLOPT_APPEND
CURLOPT_FTP_USE_EPRT
Use EPTR. See CURLOPT_FTP_USE_EPRT
CURLOPT_FTP_USE_EPSV
Use EPSV. See CURLOPT_FTP_USE_EPSV
CURLOPT_FTP_USE_PRET
Use PRET. See CURLOPT_FTP_USE_PRET
CURLOPT_FTP_CREATE_MISSING_DIRS
Create missing directories on the remote server. See CURLOPT_FTP_CREATE_MISSING_DIRS
CURLOPT_FTP_RESPONSE_TIMEOUT
Timeout for FTP responses. See CURLOPT_FTP_RESPONSE_TIMEOUT
CURLOPT_FTP_ALTERNATIVE_TO_USER
Alternative to USER. See CURLOPT_FTP_ALTERNATIVE_TO_USER
CURLOPT_FTP_SKIP_PASV_IP
Ignore the IP address in the PASV response. See CURLOPT_FTP_SKIP_PASV_IP
CURLOPT_FTPSSLAUTH
Control how to do TLS. See CURLOPT_FTPSSLAUTH
CURLOPT_FTP_SSL_CCC
Back to non-TLS again after authentication. See CURLOPT_FTP_SSL_CCC
CURLOPT_FTP_ACCOUNT
Send ACCT command. See CURLOPT_FTP_ACCOUNT
CURLOPT_FTP_FILEMETHOD
Specify how to reach files. See CURLOPT_FTP_FILEMETHOD
Что такое curl?
На самом деле, curl — это больше чем просто утилита командной строки для Linux или Windows. Это набор библиотек, в которых реализуются базовые возможности работы с URL страницами и передачи файлов. Библиотека поддерживает работу с протоколами: FTP, FTPS, HTTP, HTTPS, TFTP, SCP, SFTP, Telnet, DICT, LDAP, а также POP3, IMAP и SMTP. Она отлично подходит для имитации действий пользователя на страницах и других операций с URL адресами.
Поддержка библиотеки curl была добавлена в множество различных языков программирования и платформ. Утилита curl — это независимая обвертка для этой библиотеки. Именно на этой утилите мы и остановимся в этой статье.
Мульти запросы cURL в PHP
Обычно в скрипте PHP выполнение запросов cUrl производится последовательно, то есть друг за другом. Пока не вернется результат предыдущего запроса, новый не выполнится.
Например, если нужно собрать независимые друг от друга данные с разных сайтов, то можно организовать их параллельный сбор. Можно также произвести несвязанные вычисления или обработку данных через асинхронные запросы к скриптам в отдельных файлах.
// создание обработчиков $ch1 = curl_init(); $ch2 = curl_init(); // установка опций curl_setopt($ch1, CURLOPT_URL, "https://site1.ru"); curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch2, CURLOPT_URL, "http://www.site2.ru"); curl_setopt($ch2, CURLOPT_HEADER, 0); // создание управляющего объекта $mh = curl_multi_init(); // добавление обработчиков curl_multi_add_handle($mh,$ch1); curl_multi_add_handle($mh,$ch2); $running = null; // запуск выполнения запросов в асинхронном режиме do { curl_multi_exec($mh, $running); } while ($running > 0); // освобождение ресурсов curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh);
Функция curl_multi_exec() многократно вызывается в цикле с постусловием, где параметр $running имеет значение количества активных соединений.
Чем больше обработчиков в параллельной работе, тем больше сокращается время выполнения скрипта, поэтому нелишним будет внедрить привычку использовать эту возможность cURL в своих скриптах.
Ответ 5
Можно использовать следующий код:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$parts = explode(«\r\n\r\nHTTP/», $response);
$parts = (count($parts) > 1 ? ‘HTTP/’ : »).array_pop($parts);
list($headers, $body) = explode(«\r\n\r\n», $parts, 2);
Работает с HTTP/1.1 100 Continue перед другими заголовками.
Если вам нужно работать с глючными серверами, которые посылают только LF вместо CRLF в качестве перевода строки, вы можете использовать preg_split следующим образом:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$parts = preg_split(«@\r?\n\r?\nHTTP/@u», $response);
$parts = (count($parts) > 1 ? ‘HTTP/’ : »).array_pop($parts);
list($headers, $body) = preg_split(«@\r?\n\r?\n@u», $parts, 2);
Базовая структура
Прежде чем мы двинемся дальше к более сложным примерам, давайте рассмотрим базовую структуру cURL запроса в PHP. Существует четыре основных шага, которые нужно учитывать в каждом скрипте:
- Инициализация
- Назначение параметров
- Выполнение и выборка результата
- Освобождение памяти
// 1. инициализация $ch = curl_init(); // 2. указываем параметры, включая url curl_setopt($ch, CURLOPT_URL, "http://www.nettuts.com"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); // 3. получаем HTML в качестве результата $output = curl_exec($ch); // 4. закрываем соединение curl_close($ch);
Шаг #2 (то есть, вызов curl_setopt()) будем обсуждать в этой статье намного больше, чем все другие этапы, т.к. на этой стадии происходит всё самое интересное и полезное, что вам необходимо знать. В cURL существует огромное количество различных опций, которые должны быть указаны, для того чтобы иметь возможность сконфигурировать URL-запрос самым тщательным образом. Мы не будем рассматривать весь список целиком, а остановимся только на том, что я посчитаю нужным и полезным для этого урока. Всё остальное вы сможете изучить сами, если эта тема вас заинтересует.