Введение в cURL. Написание HTTP-запросов с помощью Curl

Для Windows 16.06.2019
Для Windows

Представляем вашему вниманию новый курс от команды The Codeby - "Тестирование Веб-Приложений на проникновение с нуля". Общая теория, подготовка рабочего окружения, пассивный фаззинг и фингерпринт, Активный фаззинг, Уязвимости, Пост-эксплуатация, Инструментальные средства, Social Engeneering и многое другое.


Источник:

cURL — это пакет программного обеспечения, состоящий из утилиты командной строки и библиотеки для передачи данных с использованием синтаксиса URL.

cURL поддерижвает множество протоколов, среди них DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet и TFTP.

Загрузить отдельный файл

Следующая команда получит содержимое URL и отобразит его в стандартном выводе (т. е. в вашем терминале).

Curl https://mi-al.ru/ > mi-al.htm % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 14378 0 14378 0 0 5387 0 --:--:-- 0:00:02 --:--:-- 5387

Сохранение вывода cURL в файл

  • -o (o нижнего регистра) результат будет сохранён в файле, заданном в командной строке
  • -O (O верхнего регистра) имя файла будет взято из URL и будет использовано для сохранения полученных данных.
$ curl -o mygettext.html http://www.gnu.org/software/gettext/manual/gettext.html

Теперь будет сохранена страница gettext.html в файле с названием ‘mygettext.html’. Когда curl запущена с опцией -o, она отображает шкалу прогресса загрузки следующим образом.

% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 66 1215k 66 805k 0 0 33060 0 0:00:37 0:00:24 0:00:13 45900 100 1215k 100 1215k 0 0 39474 0 0:00:31 0:00:31 --:--:-- 68987

Когда вы используете curl -O (O верхнего регистра), она сама по себе сохранит содержимое в файл под названием ‘gettext.html’ на локальной машине.

$ curl -O http://www.gnu.org/software/gettext/manual/gettext.html

Примечание: Когда curl должна писать данные в терминал, она отключает шкалу прогресса, чтобы не было путаницы в напечатанных данных. Мы можем исользовать ‘>’|’-o’|’-O’ опции для передачи результатов в файл.

Выборка нескольких файлов одновременно

Мы можем загрузить несколько файлов за один раз, задав все URL в командной строке.

Curl -O URL1 -O URL2

Команда ниже загрузит оба index.html и gettext.html и сохранит их с теми же именами в текущей директории.

Curl -O http://www.gnu.org/software/gettext/manual/html_node/index.html -O http://www.gnu.org/software/gettext/manual/gettext.html

Пожалуйста, обратите внимание, когда мы загружаем несколько файлов с одного сервера как показано выше, curl попытается повторно использовать соединение.

Следуем за HTTP Location в заголовках с опцией -L

По умолчанию, CURL не следует за HTTP Location в заголовках (редиректы). Когда запрошенная веб-страница перемещена в другое место, то соответствующий ответ будет передан в заголовках HTTP Location.

Например, когда кто-то печатает google.com в строке браузера из своей страны, они автоматически будут перенаправлены на ‘google.co.xx’. Это делается на основе заголовка HTTP Location как показано ниже.

Curl https://www.google.com/?gws_rd=ssl 302 Moved

302 Moved

The document has moved here.

Приведённый выше вывод говорит, что запрашиваемый документ был перемещён в ‘http://www.google.co.th/’.

Вы можете указать curl следовать редиректам, это делается с использованием опции -L как показано ниже. Теперь будет загружен исходный код html с https://www.google.co.th/?gws_rd=ssl.

Curl -L https://www.google.com/?gws_rd=ssl

Продоление/Вообновление предыдущей закачки

Используя опцию -C вы можете продолжить закачку, которая была остановлена по каким-либо причинам. Это будет полезным при обрыве загрузки больших файлов.

Если мы говорим ‘-C -’, то curl будет искать, с какого места возобновить загрузку. Мы также можем задать ‘-C <смещение>’. Заданное смещение байт будет пропущено от начала исходного файла.

Начните большую загрузку с curl и нажмите Ctrl-C для остановки посреди закачки.

$ curl -O http://www.gnu.org/software/gettext/manual/gettext.html ############## 20.1%

Закачка была остановлена на 20.1%. Используя “curl -C -” мы можем продолжить загрузку с того места, где мы остановились. Теперь загрузка продолжиться с 20.1%.

Curl -C - -O http://www.gnu.org/software/gettext/manual/gettext.html ############### 21.1%

Ограничение скорости передачи данных

Вы можете ограничить величину скорости передачи данных опцией -limit-rate. Вы можете передать максимальную скорость в качестве аргумента.

$ curl --limit-rate 1000B -O http://www.gnu.org/software/gettext/manual/gettext.html

Команда выше ограничит скорость передачи на 1000 байт/секунду. curl может использовать скорость выше на пиках. Но средняя скорость будет примерно 1000 байт/секунду.

Ниже показан индикатор прогресса для представленной выше команды. Вы можете видеть, что текущая скорость в районе 1000 байт.

% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 1 1215k 1 13601 0 0 957 0 0:21:40 0:00:14 0:21:26 999 1 1215k 1 14601 0 0 960 0 0:21:36 0:00:15 0:21:21 999 1 1215k 1 15601 0 0 962 0 0:21:34 0:00:16 0:21:18 999

Загрузить файл только если он изменён до/после заданного времени

Вы можете получить файлы, которые были изменены после определённого времени, используя опцию -z в curl. Это будет работать и для FTP и для HTTP.

$ curl -z 20-Aug-14

Команда выше загрузит yy.html только если он изменялся позднее чем заданная дата и время.

Команда выше загрузит файл file.html, если он изменялся до заданной даты и времени.

Наберите ‘man curl_getdate’ чтобы узнать больше о различных поддерживаемых синтаксисах для выражений даты.

Прохождение аутентификации HTTP в cURL

Иногда веб-сайты требуют имя пользователя и пароль для просмотра их содержимого. С помощью опции -u вы можете передать эти учётные данные из cURL на веб-сервер как показано ниже.

$ curl -u username:password URL

Примечание: По умолчанию curl использует базовую HTTP аутентификацию. Мы можем задать иные методы аутентификации используя -ntlm | -digest.

Загрузка файлов с FTP сервера

cURL может также использоваться для загрузки файлов с FTP серверов. Если заданный FTP путь является директорией, то по умолчанию будет выведен список файлов в ней.

$ curl -u ftpuser:ftppass -O ftp://ftp_server/public_html/xss.php

Команда выше загрузит файл xss.php с ftp-сервера и сохранит его в локальной директории.

$ curl -u ftpuser:ftppass -O ftp://ftp_server/public_html/

Здесь URL отсылает к директории. Следовательно, cURL сделает список файлов и директорий по заданному URL адресу.

Список/Загрузка с использованием диапазонов.

CURL поддерживает диапазоны заданные в URL. Когда дан диапазон, будут загружены соответствующие файлы внутри этого диапазона. Это будет полезным при загрузке пакетов с сайтов FTP зеркал.

$ curl ftp://ftp.uk.debian.org/debian/pool/main//

Команда выше сделает список всех пакетов в диапазоне a-z в терминале.

Выгрузка файлов на FTP-сервер

Curl также может использоваться для выгрузки на FTP-сервер с опцией -T.

$ curl -u ftpuser:ftppass -T myfile.txt ftp://ftp.testserver.com

Команда выше выгрузит файл с именем myfile.txt на FTP-сервер. Вы можете также выгрузить несколько файлов за один раз используя диапазоны.

$ curl -u ftpuser:ftppass -T "{file1,file2}" ftp://ftp.testserver.com

Опционально мы можем использовать “.” для получения из стандартного ввода и передачи его на удалённую машину.

$ curl -u ftpuser:ftppass -T - ftp://ftp.testserver.com/myfile_1.txt

Команда выше получит вывод от пользователя из стандартного ввода и сохранит содержимое на ftp-сервере под именем ‘myfile_1.txt’.

Вы можете задать ‘-T’ для каждого URL, и каждая пара адрес-файл будут определять что куда выгружать

Больше информации с увеличением вербальности и опцией трассировки

Вы можете узнать что происходит, используя опцию -v. Опция -v включает вербальный режим и будет печатать подробности.

Curl -v https://www.google.co.th/?gws_rd=ssl

Команда выше выведет следующее

* Rebuilt URL to: https://www.google.co.th/?gws_rd=ssl * Hostname was NOT found in DNS cache * Trying 27.123.17.49... * Connected to www.google.co.th (27.123.17.49) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.38.0 > Host: www.google.co.th > Accept: */* > < HTTP/1.1 200 OK < Date: Fri, 14 Aug 2015 23:07:20 GMT < Expires: -1 < Cache-Control: private, max-age=0 < Content-Type: text/html; charset=windows-874 < P3P: CP="This is not a P3P policy! See https://support.google.com/accounts/answer/151657?hl=en for more info." * Server gws is not blacklisted < Server: gws < X-XSS-Protection: 1; mode=block < X-Frame-Options: SAMEORIGIN < Set-Cookie: PREF=ID=1111111111111111:FF=0:TM=1439593640:LM=1439593640:V=1:S=FfuoPPpKbyzTdJ6T; expires=Sun, 13-Aug-2017 23:07:20 GMT; path=/; domain=.google.co.th ... ... ...

Если вам нужно больше детальной информации, тогда вы можете использовать опцию -trace. Опция -trace включит полный дамп трассировки всех входящих/исходящих данных для заданного файла

=> Send header, 169 bytes (0xa9) 0000: 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1.. 0010: 55 73 65 72 2d 41 67 65 6e 74 3a 20 63 75 72 6c User-Agent: curl .. 0060: 2e 32 2e 33 2e 34 20 6c 69 62 69 64 6e 2f 31 2e .2.3.4 libidn/1. 0070: 31 35 20 6c 69 62 73 73 68 32 2f 31 2e 32 2e 36 15 libssh2/1.2.6 0080: 0d 0a 48 6f 73 74 3a 20 77 77 77 2e 67 6f 6f 67 ..Host: www.goog 0090: 6c 65 2e 63 6f 2e 69 6e 0d 0a 41 63 63 65 70 74 le.co.xx..Accept 00a0: 3a 20 2a 2f 2a 0d 0a 0d 0a: */*.... == Info: HTTP 1.0, assume close after body <= Recv header, 17 bytes (0x11) 0000: 48 54 54 50 2f 31 2e 30 20 32 30 30 20 4f 4b 0d HTTP/1.0 200 OK. 0010: 0a

Опции увеличения вербальности и трассировки пригодятся, когда curl терпит неудачу по каким-то причинам и мы не знаем почему.

Получаем определение слова и его перевод с использованием протокола DICT

Посмотреть список доступных словарей можно так:

Curl dict://dict.org/show:db

Получить перевод слова с английского на русский можно так:

Curl dict://dict.org/d:girl:fd-eng-rus 220 pan.alephnull.com dictd 1.12.1/rf on Linux 3.14-1-amd64 <[email protected]> 250 ok 150 1 definitions retrieved 151 "girl" fd-eng-rus "English-Russian FreeDict Dictionary ver. 0.3" girl /gəːl/ девушка. 250 ok 221 bye

Больше информации по DICT можно найти прочитав RFC2229 .

Использование прокси для загрузки файла

Мы можем указать cURL использовать прокси для определённых операций, это делается опцией -x. Нам нужно задать хост и порт прокси.

$ curl -x proxysever.test.com:3128 https://www.google.co.in/?gws_rd=ssl

Отправка электронной почты с использованием протокола SMTP в curl

cURL также может быть использована для отправки электронной почты по протоколу SMTP. Вам нужно указать адрес от кого, адрес кому и IP адрес почтового сервера как показано ниже.

$ curl --mail-from [email protected] --mail-rcpt [email protected] smtp://mailserver.com

Когда команда будет введена, начнётся ожидание введения пользователем данных для письма. Когда вы закончите набирать сообщение, напечатайте. (точку) в качестве последней строки, и письмо будет немедленно отправлено.

Subject: Testing This is a test mail .

Гарант является доверенным посредником между Участниками при проведении сделки.

cURL - это специальный инструмент, который предназначен для того, чтобы передавать файлы и данные синтаксисом URL. Данная технология поддерживает множество протоколов, таких как HTTP, FTP, TELNET и многие другие. Изначально cURL было разработано для того, чтобы быть инструментом командной строки. К счастью для нас, библиотека cURL поддерживается языком программирования PHP. В этой статье мы рассмотрим некоторые расширенные функций cURL, а также затронем практическое применение полученных знаний средствами PHP.

Почему cURL?

На самом деле, существует немало альтернативных способов выборки содержания веб-страницы. Во многих случаях, главным образом из-за лени, я использовал простые PHP функции вместо cURL:

$content = file_get_contents("http://www.nettuts.com"); // или $lines = file("http://www.nettuts.com"); // или readfile("http://www.nettuts.com");

Однако данные функции не имеют фактически никакой гибкости и содержат огромное количество недостатков в том, что касается обработки ошибок и т.д. Кроме того, существуют определенные задачи, которые вы просто не можете решить благодаря этим стандартным функциям: взаимодействие с cookie, аутентификация, отправка формы, загрузка файлов и т.д.

cURL - это мощная библиотека, которая поддерживает множество различных протоколов, опций и обеспечивает подробную информацию о URL запросах.

Базовая структура

  • Инициализация
  • Назначение параметров
  • Выполнение и выборка результата
  • Освобождение памяти

// 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-запрос самым тщательным образом. Мы не будем рассматривать весь список целиком, а остановимся только на том, что я посчитаю нужным и полезным для этого урока. Всё остальное вы сможете изучить сами, если эта тема вас заинтересует.

Проверка Ошибки

Вдобавок, вы также можете использовать условные операторы для проверки выполнения операции на успех:

// ... $output = curl_exec($ch); if ($output === FALSE) { echo "cURL Error: " . curl_error($ch); } // ...

Тут прошу отметить для себя очень важный момент: мы должны использовать “=== false” для сравнения, вместо “== false”. Для тех, кто не в курсе, это поможет нам отличать пустой результат от булевого значения false, которое и будет указывать на ошибку.

Получение информации

Ещё одним дополнительным шагом является получение данных о cURL запросе, после того, как он был выполнен.

// ... curl_exec($ch); $info = curl_getinfo($ch); echo "Took " . $info["total_time"] . " seconds for url " . $info["url"]; // …

Возвращаемый массив содержит следующую информацию:

  • “url”
  • “content_type”
  • “http_code”
  • “header_size”
  • “request_size”
  • “filetime”
  • “ssl_verify_result”
  • “redirect_count”
  • “total_time”
  • “namelookup_time”
  • “connect_time”
  • “pretransfer_time”
  • “size_upload”
  • “size_download”
  • “speed_download”
  • “speed_upload”
  • “download_content_length”
  • “upload_content_length”
  • “starttransfer_time”
  • “redirect_time”

Обнаружение перенаправления в зависимости от браузера

В этом первом примере мы напишем код, который сможет обнаружить перенаправления URL, основанные на различных настройках браузера. Например, некоторые веб-сайты перенаправляют браузеры сотового телефона, или любого другого устройства.

Мы собираемся использовать опцию CURLOPT_HTTPHEADER для того, чтобы определить наши исходящие HTTP заголовки, включая название браузера пользователя и доступные языки. В конечном итоге мы сможем определить, какие сайты перенаправляют нас к разным URL.

// тестируем URL $urls = array("http://www.cnn.com", "http://www.mozilla.com", "http://www.facebook.com"); // тестируем браузеры $browsers = array("standard" => array ("user_agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)", "language" => "en-us,en;q=0.5"), "iphone" => array ("user_agent" => "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A537a Safari/419.3", "language" => "en"), "french" => array ("user_agent" => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)", "language" => "fr,fr-FR;q=0.5")); foreach ($urls as $url) { echo "URL: $url\n"; foreach ($browsers as $test_name => $browser) { $ch = curl_init(); // указываем url curl_setopt($ch, CURLOPT_URL, $url); // указываем заголовки для браузера curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: {$browser["user_agent"]}", "Accept-Language: {$browser["language"]}")); // нам не нужно содержание страницы curl_setopt($ch, CURLOPT_NOBODY, 1); // нам необходимо получить HTTP заголовки curl_setopt($ch, CURLOPT_HEADER, 1); // возвращаем результаты вместо вывода curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); // был ли HTTP редирект? if (preg_match("!Location: (.*)!", $output, $matches)) { echo "$test_name: redirects to $matches\n"; } else { echo "$test_name: no redirection\n"; } } echo "\n\n"; }

Сначала мы указываем список URL сайтов, которые будем проверять. Точнее, нам понадобятся адреса данных сайтов. Далее нам необходимо определить настройки браузера, чтобы протестировать каждый из этих URL. После этого мы воспользуемся циклом, в котором пробежимся по всем полученным результатам.

Приём, который мы используем в этом примере для того, чтобы задать настройки cURL, позволит нам получить не содержание страницы, а только HTTP-заголовки (сохраненные в $output). Далее, воспользовавшись простым regex, мы можем определить, присутствовала ли строка “Location:” в полученных заголовках.

Когда вы запустите данный код, то должны будете получить примерно следующий результат:

Создание POST запроса на определённый URL

При формировании GET запроса передаваемые данные могут быть переданы на URL через “строку запроса”. Например, когда Вы делаете поиск в Google, критерий поиска располагаются в адресной строке нового URL:

Http://www.google.com/search?q=ruseller

Для того чтобы сымитировать данный запрос, вам не нужно пользоваться средствами cURL. Если лень вас одолевает окончательно, воспользуйтесь функцией “file_get_contents()”, для того чтобы получить результат.

Но дело в том, что некоторые HTML-формы отправляют POST запросы. Данные этих форм транспортируются через тело HTTP запроса, а не как в предыдущем случае. Например, если вы заполнили форму на форуме и нажали на кнопку поиска, то скорее всего будет совершён POST запрос:

Http://codeigniter.com/forums/do_search/

Мы можем написать PHP скрипт, который может сымитировать этот вид URL запроса. Сначала давайте создадим простой файл для принятия и отображения POST данных. Назовём его post_output.php:

Print_r($_POST);

Затем мы создаем PHP скрипт, чтобы выполнить cURL запрос:

$url = "http://localhost/post_output.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;

При запуске данного скрипта вы должны получить подобный результат:

Таким образом, POST запрос был отправлен скрипту post_output.php, который в свою очередь, вывел суперглобальный массив $_POST, содержание которого мы получили при помощи cURL.

Загрузка файла

Сначала давайте создадим файл для того, чтобы сформировать его и отправить файлу upload_output.php:

Print_r($_FILES);

А вот и код скрипта, который выполняет указанный выше функционал:

$url = "http://localhost/upload_output.php"; $post_data = array ("foo" => "bar", // файл, который необходимо загрузить "upload" => "@C:/wamp/www/test.zip"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($ch); curl_close($ch); echo $output;

Когда вы хотите загрузить файл, все, что вам нужно сделать, так это передать его как обычную post переменную, предварительно поместив перед ней символ @. При запуске написанного скрипта вы получите следующий результат:

Множественный cURL

Одной из самых сильных сторон cURL является возможность создания "множественных" cURL обработчиков. Это позволяет вам открывать соединение к множеству URL одновременно и асинхронно.

В классическом варианте cURL запроса выполнение скрипта приостанавливается, и происходит ожидание завершения операции URL запроса, после чего работа скрипта может продолжиться. Если вы намереваетесь взаимодействовать с целым множеством URL, это приведёт к довольно-таки значительным затратам времени, поскольку в классическом варианте вы можете работать только с одним URL за один раз. Однако, мы можем исправить данную ситуацию, воспользовавшись специальными обработчиками.

Давайте рассмотрим пример кода, который я взял с php.net:

// создаём несколько cURL ресурсов $ch1 = curl_init(); $ch2 = curl_init(); // указываем URL и другие параметры curl_setopt($ch1, CURLOPT_URL, "http://lxr.php.net/"); curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/"); curl_setopt($ch2, CURLOPT_HEADER, 0); //создаём множественный cURL обработчик $mh = curl_multi_init(); //добавляем несколько обработчиков curl_multi_add_handle($mh,$ch1); curl_multi_add_handle($mh,$ch2); $active = null; //выполнение do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while ($active && $mrc == CURLM_OK) { if (curl_multi_select($mh) != -1) { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } //закрытие curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh);

Идея состоит в том, что вы можете использовать множественные cURL обработчики. Используя простой цикл, вы можете отследить, какие запросы ещё не выполнились.

В этом примере есть два основных цикла. Первый цикл do-while вызывает функцию curl_multi_exec(). Эта функция не блокируемая. Она выполняется с той скоростью, с которой может, и возвращает состояние запроса. Пока возвращенное значение является константой ‘CURLM_CALL_MULTI_PERFORM’, это означает, что работа ещё не завершена (например, в данный момент происходит отправка http заголовков в URL); Именно поэтому мы продолжаем проверять это возвращаемое значение, пока не получим другой результат.

В следующем цикле мы проверяем условие, пока переменная $active = "true". Она является вторым параметром для функции curl_multi_exec(). Значение данной переменной будет равно "true", до тех пор, пока какое-то из существующих изменений является активным. Далее мы вызываем функцию curl_multi_select(). Её выполнение "блокируется", пока существует хоть одно активное соединение, до тех пор, пока не будет получен ответ. Когда это произойдёт, мы возвращаемся в основной цикл, чтобы продолжить выполнение запросов.

А теперь давайте применим полученные знания на примере, который будет реально полезным для большого количества людей.

Проверяем ссылки в WordPress

Представьте себе блог с огромным количеством постов и сообщений, в каждом из которых есть ссылки на внешние интернет ресурсы. Некоторые из этих ссылок по различным причинам могли бы уже быть «мертвыми». Возможно, страница была удалена или сайт вовсе не работает.

Мы собираемся создать скрипт, который проанализирует все ссылки и найдёт незагружающиеся веб-сайты и страницы 404, после чего предоставит нам подробнейший отчёт.

Сразу же скажу, что это не пример создания плагина для WordPress. Это всего на всего хороший полигон для наших испытаний.

Давайте же наконец начнём. Сначала мы должны сделать выборку всех ссылок из базы данных:

// конфигурация $db_host = "localhost"; $db_user = "root"; $db_pass = ""; $db_name = "wordpress"; $excluded_domains = array("localhost", "www.mydomain.com"); $max_connections = 10; // инициализация переменных $url_list = array(); $working_urls = array(); $dead_urls = array(); $not_found_urls = array(); $active = null; // подключаемся к MySQL if (!mysql_connect($db_host, $db_user, $db_pass)) { die("Could not connect: " . mysql_error()); } if (!mysql_select_db($db_name)) { die("Could not select db: " . mysql_error()); } // выбираем все опубликованные посты, где есть ссылки $q = "SELECT post_content FROM wp_posts WHERE post_content LIKE "%href=%" AND post_status = "publish" AND post_type = "post""; $r = mysql_query($q) or die(mysql_error()); while ($d = mysql_fetch_assoc($r)) { // делаем выборку ссылок при помощи регулярных выражений if (preg_match_all("!href=\"(.*?)\"!", $d["post_content"], $matches)) { foreach ($matches as $url) { $tmp = parse_url($url); if (in_array($tmp["host"], $excluded_domains)) { continue; } $url_list = $url; } } } // убираем дубликаты $url_list = array_values(array_unique($url_list)); if (!$url_list) { die("No URL to check"); }

Сначала мы формируем конфигурационные данные для взаимодействия с базой данных, далее пишем список доменов, которые не будут участвовать в проверке ($excluded_domains). Также мы определяем число, характеризующее количество максимальных одновременных соединений, которые мы будем использовать в нашем скрипте ($max_connections). Затем мы присоединяемся к базе данных, выбираем посты, которые содержат ссылки, и накапливаем их в массив ($url_list).

Следующий код немного сложен, так что разберитесь в нём от начала до конца:

// 1. множественный обработчик $mh = curl_multi_init(); // 2. добавляем множество URL for ($i = 0; $i < $max_connections; $i++) { add_url_to_multi_handle($mh, $url_list); } // 3. инициализация выполнения do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); // 4. основной цикл while ($active && $mrc == CURLM_OK) { // 5. если всё прошло успешно if (curl_multi_select($mh) != -1) { // 6. делаем дело do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); // 7. если есть инфа? if ($mhinfo = curl_multi_info_read($mh)) { // это значит, что запрос завершился // 8. извлекаем инфу $chinfo = curl_getinfo($mhinfo["handle"]); // 9. мёртвая ссылка? if (!$chinfo["http_code"]) { $dead_urls = $chinfo["url"]; // 10. 404? } else if ($chinfo["http_code"] == 404) { $not_found_urls = $chinfo["url"]; // 11. рабочая } else { $working_urls = $chinfo["url"]; } // 12. чистим за собой curl_multi_remove_handle($mh, $mhinfo["handle"]); // в случае зацикливания, закомментируйте данный вызов curl_close($mhinfo["handle"]); // 13. добавляем новый url и продолжаем работу if (add_url_to_multi_handle($mh, $url_list)) { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } } } // 14. завершение curl_multi_close($mh); echo "==Dead URLs==\n"; echo implode("\n",$dead_urls) . "\n\n"; echo "==404 URLs==\n"; echo implode("\n",$not_found_urls) . "\n\n"; echo "==Working URLs==\n"; echo implode("\n",$working_urls); function add_url_to_multi_handle($mh, $url_list) { static $index = 0; // если у нас есть ещё url, которые нужно достать if ($url_list[$index]) { // новый curl обработчик $ch = curl_init(); // указываем url curl_setopt($ch, CURLOPT_URL, $url_list[$index]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_NOBODY, 1); curl_multi_add_handle($mh, $ch); // переходим на следующий url $index++; return true; } else { // добавление новых URL завершено return false; } }

Тут я попытаюсь изложить всё по полочкам. Числа в списке соответствуют числам в комментарии.

  1. 1. Создаём множественный обработчик;
  2. 2. Функцию add_url_to_multi_handle() мы напишем чуть позже. Каждый раз, когда она будет вызываться, начнётся обработка нового url. Первоначально, мы добавляем 10 ($max_connections) URL;
  3. 3. Для того чтобы начать работу, мы должны запустить функцию curl_multi_exec(). До тех пор, пока она будет возвращать CURLM_CALL_MULTI_PERFORM, нам ещё есть, что делать. Это нам нужно, главным образом, для того, чтобы создать соединения;
  4. 4. Далее следует основной цикл, который будет выполняться до тех пор, пока у нас есть хоть одно активное соединение;
  5. 5. curl_multi_select() зависает в ожидании, пока поиск URL не завершится;
  6. 6. И снова мы должны заставить cURL выполнить некоторую работу, а именно, сделать выборку данных возвращаемого ответа;
  7. 7. Тут происходит проверка информации. В результате выполнения запроса будет возвращён массив;
  8. 8. В возвращенном массиве присутствует cURL обработчик. Его мы и будем использовать для того, чтобы выбрать информацию об отдельном cURL запросе;
  9. 9. Если ссылка была мертва, или время выполнения скрипта вышло, то нам не следует искать никакого http кода;
  10. 10. Если ссылка возвратила нам страницу 404, то http код будет содержать значение 404;
  11. 11. В противном случае, перед нами находится рабочая ссылка. (Вы можете добавить дополнительные проверки на код ошибки 500 и т.д...);
  12. 12. Далее мы удаляем cURL обработчик, потому что больше в нём не нуждаемся;
  13. 13. Теперь мы можем добавить другой url и запустить всё то, о чём говорили до этого;
  14. 14. На этом шаге скрипт завершает свою работу. Мы можем удалить всё, что нам не нужно и сформировать отчет;
  15. 15. В конце концов, напишем функцию, которая будет добавлять url в обработчик. Статическая переменная $index будет увеличиваться каждый раз, когда данная функция будет вызвана.

Я использовал данный скрипт на своем блоге (с некоторыми неработающими ссылками, которые добавил нарочно для того, чтобы протестировать его работу) и получил следующий результат:

В моём случае, скрипту потребовалось чуть меньше чем 2 секунды, чтобы пробежаться по 40 URL. Увеличение производительности является существенным при работе с еще большим количеством URL адресов. Если вы открываете десять соединений одновременно, то скрипт может выполниться в десять раз быстрее.

Пару слов о других полезных опциях cURL

HTTP Аутентификация

Если на URL адресе есть HTTP аутентификация, то вы без труда можете воспользоваться следующим скриптом:

$url = "http://www.somesite.com/members/"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // указываем имя и пароль curl_setopt($ch, CURLOPT_USERPWD, "myusername:mypassword"); // если перенаправление разрешено curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // то сохраним наши данные в cURL curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1); $output = curl_exec($ch); curl_close($ch);

FTP загрузка

В PHP также существует библиотека для работы с FTP, но вам ничего не мешает и тут воспользоваться средствами cURL:

// открываем файл $file = fopen("/path/to/file", "r"); // в url должно быть следующее содержание $url = "ftp://username:[email protected]:21/path/to/new/file"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_UPLOAD, 1); curl_setopt($ch, CURLOPT_INFILE, $fp); curl_setopt($ch, CURLOPT_INFILESIZE, filesize("/path/to/file")); // указывам ASCII мод curl_setopt($ch, CURLOPT_FTPASCII, 1); $output = curl_exec($ch); curl_close($ch);

Используем Прокси

Вы можете выполнить свой URL запрос через прокси:

$ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"http://www.example.com"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // указываем адрес curl_setopt($ch, CURLOPT_PROXY, "11.11.11.11:8080"); // если необходимо предоставить имя пользователя и пароль curl_setopt($ch, CURLOPT_PROXYUSERPWD,"user:pass"); $output = curl_exec($ch); curl_close ($ch);

Функции обратного вызова

Также существует возможность указать функцию, которая будет срабатывать ещё до завершения работы cURL запроса. Например, пока содержание ответа загружается, вы можете начать использовать данные, не дожидаясь полной загрузки.

$ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"http://net.tutsplus.com"); curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function"); curl_exec($ch); curl_close ($ch); function progress_function($ch,$str) { echo $str; return strlen($str); }

Подобная функция ДОЛЖНА возвращать длину строки, что является обязательным требованием.

Заключение

Сегодня мы познакомились с тем, как можно применить библиотеку cURL в своих корыстных целях. Я надеюсь, что вам понравилась данная статья.

Спасибо! Удачного дня!

Жизнь веб-разработчика омрачена сложностями. Особенно неприятно, когда источник этих сложностей неизвестен. То ли это проблема с отправкой запроса, то ли с ответом, то ли со сторонней библиотекой, то ли внешний API глючит? Существует куча различных прилад, способных упростить нам жизнь. Вот некоторые инструменты командной строки, которые лично я считаю бесценными.

cURL
cURL - программа для передачи данных по различным протоколам, похожая на wget. Основное отличие в том, что по умолчанию wget сохраняет в файл, а cURL выводит в командную строку. Так можно очень просто посмотреть контент веб-сайта. Например, вот как быстро получить свой текущий внешний IP:

$ curl ifconfig.me 93.96.141.93
Параметры -i (показывать заголовки) и -I (показывать только заголовки) делают cURL отличным инструментом для дебаггинга HTTP-ответов и анализа того, что конкретно сервер вам отправляет:

$ curl -I сайт HTTP/1.1 200 OK Server: nginx Date: Thu, 18 Aug 2011 14:15:36 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Keep-alive: timeout=25
Параметр -L тоже полезный, он заставляет cURL автоматически следовать по редиректам. cURL поддерживает HTTP-аутентификацию, cookies, туннелирование через HTTP-прокси, ручные настройки в заголовках и многое, многое другое.

Siege
- инструмент для нагрузочного тестирования. Плюс, у него есть удобная опция -g , которая очень похожа на curl –iL , но вдобавок показывает вам ещё и заголовки http-запроса. Вот пример с google.com (некоторые заголовки удалены для краткости):

$ siege -g www.google.com GET / HTTP/1.1 Host: www.google.com User-Agent: JoeDog/1.00 (X11; I; Siege 2.70) Connection: close HTTP/1.1 302 Found Location: http://www.google.co.uk/ Content-Type: text/html; charset=UTF-8 Server: gws Content-Length: 221 Connection: close GET / HTTP/1.1 Host: www.google.co.uk User-Agent: JoeDog/1.00 (X11; I; Siege 2.70) Connection: close HTTP/1.1 200 OK Content-Type: text/html; charset=ISO-8859-1 X-XSS-Protection: 1; mode=block Connection: close
Но для чего Siege действительно великолепно подходит, так это для нагрузочного тестирования. Как и апачевский бенчмарк ab , он может отправить множество параллельных запросов к сайту и посмотреть, как он справляется с трафиком. В следующем примере показано, как мы тестируем Google с помощью 20 запросов в течение 30 секунд, после чего выводится результат:

$ siege -c20 www.google.co.uk -b -t30s ... Lifting the server siege... done. Transactions: 1400 hits Availability: 100.00 % Elapsed time: 29.22 secs Data transferred: 13.32 MB Response time: 0.41 secs Transaction rate: 47.91 trans/sec Throughput: 0.46 MB/sec Concurrency: 19.53 Successful transactions: 1400 Failed transactions: 0 Longest transaction: 4.08 Shortest transaction: 0.08
Одна из самых полезных функций Siege - то, что он может работать не только с одним адресом, но и со списком URL’ов из файла. Это отлично подходит для нагрузочного тестирования, потому что можно моделировать реальный трафик на сайте, а не просто жать один и тот же URL снова и снова. Например, вот как использовать Siege, чтобы нагрузить сервер, используя адреса из вашего лога Apache:

$ cut -d " " -f7 /var/log/apache2/access.log > urls.txt $ siege -c -b -f urls.txt
Ngrep
Для серьёзного анализа трафика существует Wireshark с тысячами настроек, фильтров и конфигураций. Есть также версия для командной строки tshark . Но для простых задач функционал Wireshark я считаю избыточным. Так что до тех пор, пока мне не нужно мощное оружие, я использую . Он позволяет делать с сетевыми пакетами то же самое, что grep делает с файлами.

Для веб-трафика вы почти всегда захотите использовать параметр -W , чтобы сохранить форматирование строк, а также параметр -q , который скрывает избыточную информацию о неподходящих пакетах. Вот пример команды, которая перехватывает все пакеты с командой GET или POST:

Ngrep -q -W byline "^(GET|POST) .*"
Вы можете добавить дополнительный фильтр для пакетов, например, по заданному хосту, IP-адресу или порту. Вот фильтр для всего входящего и исходящего трафика на google.com, порт 80, который содержит слово “search”.

Ngrep -q -W byline "search" host www.google.com and port 80

c URL очень полезный инструмент командной строки для передачи данных от или к серверу. Curl поддерживает различные протоколы, такие как FILE, HTTP, HTTPS, IMAP, IMAPS, LDAP, DICT, LDAPS, TELNET, FTPS, GOPHER, RTMP, RTSP, SCP, SFTP, POP3, POP3S, SMB, SMBS, SMTP, SMTPS, и TFTP.

cURL может быть использован самыми различными и интересными способами. С помощью этого инструмента вы можете скачать, загрузить файлы и управлять ими, проверить свой адрес электронной почты, или даже обновлять свой статус на некоторых веб – сайтах социальных медиа или проверить погоду на улице. В этой статье мы рассмотрим пять наиболее полезных и основных видов использования инструмента cURL на любой .

1. Проверьте URL

Одним из наиболее распространенных и простейших применений cURL печатает саму команду, а затем URL, который вы хотите проверить

Curl https://domain.ru

Эта команда будет отображать содержимое URL на вашем терминале

2. Сохраните вывод URL в файл

Curl -o website https://domain.ru % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 41793 0 41793 0 0 275k 0 --:--:-- --:--:-- --:--:-- 2.9M

В этом примере, вывод будет сохранен в файл с именем ‘website’ в текущем рабочем каталоге.

3. Загрузка файлов с помощью Curl

Вы можете скачивать файлы при помощи Curl, путем добавления опции -o к команде. Он используется для сохранения файлов на локальном сервере с теми же именами, как и на удаленном сервере

Curl -O https://domain.ru/file.zip

В этом примере архив ‘file.zip’ будет загружен в текущий рабочий каталог.

Вы также можете загрузить файл с другим именем, добавив опцию -o к cURL.

Curl -o archive.zip https://domain.ru/file.zip

Таким образом, архив ‘file.zip’ будет загружен и сохранен как ‘Archive.zip’.

cURL может быть также использован для загрузки нескольких файлов одновременно, как показано в приведенном ниже примере

Curl -O https://domain.ru/file.zip -O https://domain.com/file2.zip

Curl также можно использовать для загрузки файлов надежно через SSH с помощью следующей команды

Curl -u user sftp://server.domain.ru/path/to/file

Обратите внимание, что вы должны использовать полный путь к файлу, который требуется загрузить

4. Взять информацию из заголовка HTTP веб-сайта

Вы можете легко получить информацию заголовка HTTP из любого веб-сайта, добавив опцию -I (‘i’) к cURL.

Curl -I http://domain.ru HTTP/1.1 200 OK Date: Sun, 16 Oct 2016 23:37:15 GMT Server: Apache/2.4.23 (Unix) X-Powered-By: PHP/5.6.24 Connection: close Content-Type: text/html; charset=UTF-8

5. Доступ к FTP-серверу

Чтобы получить доступ к FTP-серверу с помощью Curl, надо использовать следующую команду

Curl ftp://ftp.domain.ru --user username:password

Curl будет подключаться к FTP-серверу и выведет список всех файлов и каталогов в домашнем каталоге пользователя

Вы можете скачать файл с помощью FTP

Curl ftp://ftp.domain.ru/file.zip --user username:password

и загрузить файл на сервер FTP

Curl -T file.zip ftp://ftp.domain.ru/ --user username:password

Вы можете проверить страницу Curl вручную, чтобы увидеть все доступные опции cURL и его функциональные возможности

Man curl

PS. Если вам понравился этот пост, пожалуйста поделитесь им с друзьями в социальных сетях с помощью кнопок ниже или просто оставьте комментарий. Благодарю.

21 ответ

Возможно, у вас уже есть завиток

Возможно, вам не нужно ничего скачивать:

  • Если вы используете Windows 10 версии 1803 или выше, ваша ОС поставляется с копией curl , уже настроенной и готовой к использованию.
  • Если у вас есть более эзотерические потребности (например, вам нужны сборки cygwin, сторонние сборки, libcurl, файлы заголовков, исходные коды и т.д.), Используйте мастер загрузки curl. После ответа на пять вопросов вам будет представлен список ссылок для скачивания.

    Извлечение и настройка скручивания

    Найдите curl.exe в вашем загруженном пакете; это наверное под bin\ .

    Выберите место на жестком диске, которое будет служить постоянным домом для завитков:

    • Если вы хотите сделать curl своей собственной папкой, подойдут C:\Program Files\curl\ или C:\curl\ .
    • Если у вас много свободных исполняемых файлов и вы не хотите добавлять много отдельных папок в PATH , используйте для этой цели одну папку, например C:\Program Files\tools\ или C:\tools\ .

    Поместите curl.exe в папку. И никогда не перемещайте папку или ее содержимое.

    Затем вы захотите сделать curl доступным в любом месте командной строки. Для этого добавьте папку в PATH , вот так:

    1. Щелкните меню "Пуск" Windows 10. Начните вводить "окружение".
    2. Вы увидите результат поиска. Отредактируйте системные переменные среды . Выбери это.
    3. Откроется окно "Свойства системы". Нажмите кнопку Переменные среды внизу.
    4. Выберите переменную "Путь" в разделе "Системные переменные" (нижнее поле). Нажмите кнопку Изменить .
    5. Нажмите кнопку " Добавить" и вставьте путь к папке, в которой находится curl.exe .
    6. Нажмите OK, если необходимо. Закройте открытые окна консоли и снова откройте, чтобы они получили новый PATH .

    Теперь наслаждайтесь вводом curl в любой командной строке. Время веселиться!

    Чтобы запустить завиток из командной строки

    a) Щелкните правой кнопкой мыши значок "Мой компьютер"

    b) Выберите "Свойства"

    d) Перейдите на вкладку [Дополнительно] - кнопка "Переменные среды"

    e) В разделе "Системная переменная" выберите "Путь" и "Изменить"

    f) Добавьте точку с запятой, а затем путь туда, куда вы поместили свой curl.exe(например, D:\software\curl)

Теперь вы можете запустить из командной строки, набрав:

Curl www.google.com

Начиная с Windows 10 версии 1803 (и более ранних, с инсайдерской сборкой 17063), вы больше не устанавливаете curl . Windows содержит собственный curl.exe (и tar.exe) в C:\Windows\System32\ , к которому вы можете обращаться прямо из обычного CMD .

C:\Users\vonc>C:\Windows\System32\curl.exe --version curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL Release-Date: Protocols: dict file ftp ftps http https imap imaps pop3 pop3s smtp smtps telnet tftp Features: AsynchDNS IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL C:\Users\vonc>C:\Windows\System32\tar.exe --version bsdtar 3.3.2 - libarchive 3.3.2 zlib/1.2.5.f-ipp

Вероятно, стоит отметить, что Powershell v3 и более поздних версий содержит командлет Invoke-WebRequest, который имеет некоторые возможности скручивания. Вероятно, стоит упомянуть и командлеты New-WebServiceProxy и Invoke-RestMethod .

Я не уверен, что они подойдут вам или нет, но, хотя я и не Windows, я должен сказать, что нахожу объектный подход, который использует PS, гораздо проще работать с такими утилитами, как curl, wget и т.д. Они могут стоить взглянуть на

Вы можете создать последнюю версию curl, openssl, libssh2 и zlib в 3 простых шаги, следуя этот учебник.

Curl построен статически, поэтому вам не нужно распространять необходимое динамическое время выполнения.

Вы также можете скачать предварительно созданную версию (x86 и x64) из

Я искал процесс загрузки Curl и каждый, где они сказали, копирует файл curl.exe в System32 , но они не предоставили прямую ссылку. так что здесь можно наслаждаться curl.exe легко в папке bin просто

разархивируйте его, а затем перейдите в папку bin там, где вы получите exe файл

Думал, что напишу именно то, что сделал (Windows 10, 64-битная версия):

Выберите исполняемый файл curl.

Выберите Win64.

Выберите универсальный.

Выбирай любой.

curl версия: 7.53.1 - SSL включен SSH включен. Предоставлено: Виктор Шакац. Этот пакет является исполняемым типом curl. По этой ссылке вы получите предварительно скомпилированный двоичный файл curl (или, в некоторых случаях, используя информацию, предоставленную на странице, по которой вас ведет эта ссылка). Вы можете или не можете установить libcurl как общую библиотеку /DLL. Файл упакован с использованием 7zip. 7zip - это формат архивирования файлов.

Нажмите скачать.

У вас должен быть файл curl-7.53.1-win64-mingw.7z в вашей папке загрузок.

Установите 7-Zip, если у вас его нет.

Щелкните правой кнопкой мыши, 7-Zip, Извлечь здесь. Скопируйте и вставьте извлеченный файл куда-нибудь вроде Z:\Tools\

Если вы посмотрите в папку bin, вы увидите curl.exe. Если вы дважды щелкните по нему, окно быстро вспыхнет и исчезнет. Чтобы запустить его, вам нужно использовать командную строку. Перейдите в папку bin и введите curl, а затем свои параметры, чтобы сделать запрос. Вы должны использовать двойные кавычки . Одинарные кавычки не будут работать с curl в Windows.

Теперь вам нужно добавить curl в пользовательскую переменную Path, чтобы вам не пришлось переходить в нужную папку для запуска программы. Перейдите в раздел "Этот ПК", "Компьютер", "Свойства системы", "Дополнительные параметры системы", войдите в систему как администратор (вы не являетесь администратором, верно? Верно?). Переменные среды, системные переменные, посмотрите список и выберите "Путь", затем "Редактировать", затем Новый, то, например,

Z:\Tools\завиток-7.53.1-win64-MinGW\Bin

Вы можете добавить обратную косую черту, если хотите, я не думаю, что это имеет значение. Нажмите кнопку перемещения вверх до тех пор, пока она не окажется вверху списка, и вы сможете легко увидеть ее с предыдущего экрана. Нажмите OK, OK, OK, затем откройте командную строку, и вы можете запустить curl, набрав curl из любой папки, как любой пользователь. Не забывайте свои двойные кавычки.

Это ответ, который я хотел бы получить.

Этот установщик облегчил мне http://www.confusedbycode.com/curl/



Рекомендуем почитать

Наверх