Написание HTTP-запросов с помощью Curl. Инструменты командной строки для веб-разработчика Использование curl

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 в файл
Мы можем сохранить результат команды curl в файл, используя опции -o/-O.
  • -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.

Приведённый выше вывод говорит, что запрашиваемый документ был перемещён в ‘

Скрыто от гостей

.
Вы можете указать curl следовать редиректам, это делается с использованием опции -L как показано ниже. Теперь будет загружен исходный код html с

Скрыто от гостей

.

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.

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

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

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

$ curl -u username:password URL

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


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 включит полный дамп трассировки всех входящих/исходящих данных для заданного файла
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 можно найти прочитав

Скрыто от гостей

.

Использование прокси для загрузки файла
Мы можем указать 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 .

У Вас в браузере заблокирован JavaScript. Разрешите JavaScript для работы сайта!

Curl

PHP поддерживает libcurl, библиотеку, созданную Daniel"ом Stenberg"ом, которая даёт возможность соединяться с серверами различных типов и по разным протоколам.
libcurl в настоящее время поддерживает протоколы http, https, ftp, gopher, telnet, dict, file и ldap.
libcurl также поддерживает сертификаты HTTPS, HTTP POST, HTTP PUT, загрузку по FTP (это можно сделать также РНР-расширением ftp), загрузку на основе форм HTTP, прокси, куки и аутентификацию user+password.

Эти функции были введены в PHP 4.0.2.

curl_init

curl_init - инициализирует CURL-сессию.

Описание

resource curl_init ()

Функция curl_init() инициализирует новую сессию и возвратит CURL-дескриптор для использования в функциях , и . Если необязательный параметр url предоставлен, то опция CURLOPT_URL получит значение этого параметра. Вы можете вручную устанавливать его с помощью функции .

curl_setopt

curl_setopt - устанавливает опции для CURL-трансфера/transfer.

Описание

bool curl_setopt (resource ch, string option, mixed value)

Функция curl_setopt() устанавливает опции для CURL-сессии, идентифицируемой параметром ch . Параметр option является опцией, которую вы хотите установить, а value это значение опции option .

Параметр value должен быть long для следующих опций (специфицированных параметром option ):

  • CURLOPT_INFILESIZE : Если вы выгружаете файл на удалённый сайт, эта опция должна использоваться, для того чтобы сообщит PHP, какой будет ожидаемый размер infile.
  • CURLOPT_VERBOSE : Установите эту опцию в ненулевое значение, если вы хотите, чтобы CURL сообщала обо всех действиях.
  • CURLOPT_HEADER : Установите эту опцию в ненулевое значение, если вы хотите, чтобы шапка/header включалась в вывод.
  • CURLOPT_NOPROGRESS : Установите эту опцию в ненулевое значение, если вы не хотите, чтобы PHP выводил индикатор процесса CURL-трансфера. (PHP автоматически устанавливает эту опцию в ненулевое значение, изменять её необходимо лишь при отладке.)
  • CURLOPT_NOBODY : Установите эту опцию в ненулевое значение, если вы не хотите, чтобы тело/body включалось в вывод.
  • CURLOPT_FAILONERROR : Установите эту опцию в ненулевое значение, если вы хотите, чтобы PHP завершал работу скрыто, если возвращаемый HTTP-код имеет значение выше 300. По умолчанию страница возвращается нормально с игнорированием кода.
  • CURLOPT_UPLOAD : Установите эту опцию в ненулевое значение, если вы хотите, чтобы PHP подготавливал файл к выгрузке.
  • CURLOPT_POST : Установите эту опцию в ненулевое значение, если вы хотите, чтобы PHP выполнял регулярный HTTP POST. Этот POST имеет нормальный вид application/x-www-form-urlencoded , чаще всего используемый HTML-формами.
  • CURLOPT_FTPLISTONLY : Установите эту опцию в ненулевое значение, и PHP будет выводит листинг имён FTP-директории.
  • CURLOPT_FTPAPPEND : Установите эту опцию в ненулевое значение, и PHP будет присоединять к удалённому/remote файлу, вместо его перезаписи.
  • CURLOPT_NETRC : Установите эту опцию в ненулевое значение, и PHP будет сканировать ваш файл ~./netrc с целью поиска ваших username и password для удалённого сайта, с которым вы устанавливаете соединение.
  • CURLOPT_FOLLOWLOCATION : Установите эту опцию в ненулевое значение, чтобы следовать любому "Location: " header, который сервер высылает как часть HTTP header"а (заметьте, что это рекурсия, PHP будет следовать за всеми "Location: "-header"ами, которые высылаются.)
  • CURLOPT_PUT : Установите эту опцию в ненулевое значение, чтобы HTTP PUT файл. Файл для PUT обязан быть установлен с помощью CURLOPT_INFILE и CURLOPT_INFILESIZE.
  • CURLOPT_MUTE : Установите эту опцию в ненулевое значение, и PHP будет работать скрыто в отношении CURL-функций.
  • CURLOPT_TIMEOUT : Передаёт long как параметр, который содержит максимальное время в секундах, которое вы отводите для работы CURL-функций.
  • CURLOPT_CONNECTTIMEOUT : Передаёт long как параметр, который содержит максимальное время в секундах, которое вы отводите для ожидания при попытке подключения. Используйте 0 чтобы ждать бесконечно.
  • CURLOPT_LOW_SPEED_LIMIT : Передаёт long как параметр, который содержит скорость трансфера в байтах в секунду, ниже которого трансфер должен работать в процессе выполнения CURLOPT_LOW_SPEED_TIME, в секундах, чтобы PHP считал его слишком медленным и прерывал его.
  • CURLOPT_LOW_SPEED_TIME : Передаёт long как параметр, который содержит время в секундах, ниже которого трансфер должен работать в процессе выполнения CURLOPT_LOW_SPEED_LIMIT, чтобы PHP считал его слишком медленным и прерывал его.
  • CURLOPT_RESUME_FROM : Передаёт long как параметр, который содержит смещение в байтах, с которого трансфер должен стартовать.
  • CURLOPT_SSLVERSION : Передаёт long как параметр, который содержит используемую версию SSL (2 или 3). По умолчанию PHP пытается определить это сам, хотя в некоторых случаях вы обязаны устанавливать это вручную.
  • CURLOPT_SSL_VERIFYHOST : Передаёт long, если CURL должна проверять Common-имя peer-сертификата в SSL handshake/"рукопожатие". Значение 1 указывает, что мы должны проверить существование общего /common имени, значение 2 указывает, что мы должны убедиться в совпадении с предоставленным hostname.
  • CURLOPT_TIMECONDITION : Передаёт long как параметр, который определяет, как рассматривается CURLOPT_TIMEVALUE. Вы можете установить этот параметр для TIMECOND_IFMODSINCE или TIMECOND_ISUNMODSINCE. Это действует только для HTTP.
  • CURLOPT_TIMEVALUE : Передаёт long как параметр, который является временем в секундах, прошедшим после 1 января 1970. Это время используется, как специфицировано опцией CURLOPT_TIMEVALUE, или по умолчанию будет использоваться TIMECOND_IFMODSINCE.
  • CURLOPT_RETURNTRANSFER : Передаёт ненулевое значение, если вы хотите, чтобы CURL непосредственно возвращала полученную информацию, вместо её печати напрямую.

Параметр value должен быть строкой для следующих значений параметра option :

Следующие опции ожидают дескриптора файла, который получается с помощью функции fopen() :

  • CURLOPT_FILE : Файл, куда должен быть помещён вывод вашего трансфера, по умолчанию это STDOUT.
  • CURLOPT_INFILE : Файл, из которого приходит ввод вашего трансфера.
  • CURLOPT_WRITEHEADER : Файл для записи header-части вывода.
  • CURLOPT_STDERR : Файл для записи ошибок, вместо stderr.

Параметр value long write_callback (resource ch, string data){ ... return strlen($data);} option :

  • CURLOPT_WRITEFUNCTION : .
  • CURLOPT_HEADERFUNCTION : .

Параметр value должен быть функцией следующего вида string read_callback (resource ch, resource fd, long length){} для следующих значений параметра option :

  • CURLOPT_READFUNCTION : .

curl_exec

curl_exec - выполняет CURL-сессию.

Описание

bool curl_exec (resource ch)

Эта функция должна вызываться после того, как вы инициализируете сессию CURL и все опции этой сессии уже установлены. Её назначение в том, чтобы просто выполнить предопределённую CURL-сессию (заданную в параметре ch ).

curl_close

curl_close - закрывает CURL-сессию.

Описание

void curl_close (resource ch)

Эта функция закрывает сессию CURL и освобождает все ресурсы. CURL-дескриптор ch также удаляется.

curl_errno

curl_errno - возвращает целое число, содержащее номер последней ошибки.

Описание

Пример 1. Инициализация новой сессии CURL и получение web-страницы.
Пример 2. Использование модуля CURL РНР для получения example.com
Пример 3. Проверка доступности URL с помощью CURL РНР
Пример 4. Отделение заголовка от тела, полученного с помощью CURL РНР
Пример 5. Определение адреса перехода URL с помощью CURL РНР
the problem: curl_setopt($ch,FOLLOW_LOCATION,1); the error: trouble with open_basedir and safe_mode the solution: a function already developed by someone the solution n 2: the same function, modifed, works great for me.. = $curl_max_loops) { $curl_loops = 0; return FALSE; } curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($ch); list($header, $data) = explode("\n\n", $data, 2); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($http_code == 301 || $http_code == 302) { $matches = ; preg_match("/Location:(.*?)\n/", $header, $matches); $url = @parse_url(trim(array_pop($matches))); if (!$url) { //couldn"t process the url to redirect to $curl_loops = 0; return $data; } $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)); if (!$url["scheme"]) $url["scheme"] = $last_url["scheme"]; if (!$url["host"]) $url["host"] = $last_url["host"]; if (!$url["path"]) $url["path"] = $last_url["path"]; $new_url = $url["scheme"] . "://" . $url["host"] . $url["path"] . ($url["query"]?"?".$url["query"]:""); curl_setopt($ch, CURLOPT_URL, $new_url); debug("Redirecting to", $new_url); return curl_redir_exec($ch); } else { $curl_loops=0; return $data; } } ?>
just use this function without de FOLLOW_LOCATION and should work. the problem was that when you get to the line where you return the data if http_code was different than 301 oe 302, $data has obsolete information or none. so $debbbb does the job.
Пример 6. Разбор cookie из заголовка с помощью CURL РНР
Sometimes you can"t use CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE becoz of the server php-settings(They say u may grab any files from server using these options). Here is the solution 1)Don"t use CURLOPT_FOLLOWLOCATION 2)Use curl_setopt($ch, CURLOPT_HEADER, 1) 3)Grab from the header cookies like this: preg_match_all("|Set-Cookie: (.*);|U", $content, $results); $cookies = implode(";", $results); 4)Set them using curl_setopt($ch, CURLOPT_COOKIE, $cookies);
Пример 7. Разбор cookie из заголовка с помощью CURL РНР
As Yevgen mentioned earlier sometimes we can"t use CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE. Below is a header callback function I wrote back in January that lets you maintain cookies between cURL requests. Cookies are added to $ch during all requests even during redirection, so you can use it together with CURLOPT_FOLLOWLOCATION. Here is the code: function read_header($ch, $string) { global $location; #keep track of location/redirects global $cookiearr; #store cookies here global $ch; # ^overrides the function param $ch # this is okay because we need to # update the global $ch with # new cookies $length = strlen($string); if(!strncmp($string, "Location:", 9)) { #keep track of last redirect $location = trim(substr($string, 9, -1)); } if(!strncmp($string, "Set-Cookie:", 11)) { #get the cookie $cookiestr = trim(substr($string, 11, -1)); $cookie = explode(";", $cookiestr); $cookie = explode("=", $cookie); $cookiename = trim(array_shift($cookie)); $cookiearr[$cookiename] = trim(implode("=", $cookie)); } $cookie = ""; if(trim($string) == "") { #execute only at end of header foreach ($cookiearr as $key=>$value) { $cookie .= "$key=$value; "; } curl_setopt($ch, CURLOPT_COOKIE, $cookie); } return $length; } curl_setopt($ch, CURLOPT_HEADERFUNCTION, "read_header"); This code assumes that you will reuse $ch without initializing it every time (call curl_init only once, in the beginning). If you need to initialize $ch again at any point in your code you can access the currently stored cookies in $cookiearr and include them in the new $ch. I wrote this function before I had enough experience with regular expressions so you won"t find any preg_match calls here. I have used this code for quite a while and without any problems accessing gmail, yahoo, hotmail, aol etc. where I had to go through login and a few pages before getting to what I was looking for.
Пример 8. Установка обработчика загрузки заголовка с помощью CURL РНР
Using cURL, I needed to call a third-party script which was returning binary data as attachment to pass on retrieved data again as attachment. Problem was that the third-party script occassionally returned HTTP errors and I wanted to avoid passing on zero-length attachment in such case. Combination of using CURLOPT_FAILONERROR and CURLOPT_HEADERFUNCTION callback helped to process the third-party script HTTP errors neatly: function curlHeaderCallback($resURL, $strHeader) { if (preg_match("/^HTTP/i", $strHeader)) { header($strHeader); header("Content-Disposition: attachment; filename="file-name.zip""); } return strlen($strHeader); } $resURL = curl_init("http://сайт/"); curl_setopt($resURL, CURLOPT_BINARYTRANSFER, 1); curl_setopt($resURL, CURLOPT_HEADERFUNCTION, "curlHeaderCallback"); curl_setopt($resURL, CURLOPT_FAILONERROR, 1); curl_exec ($resURL); $intReturnCode = curl_getinfo($resURL, CURLINFO_HTTP_CODE); curl_close ($resURL); if ($intReturnCode != 200) { print "Ошибка с кодом: " . $intReturnCode; }
Пример 9. Сохранение страницы в файл с подсчетом скорости передачи с помощью CURL РНР
WritePageToFile("http://es.php.net", "es.php.net.txt"); function WritePageToFile($sHTMLpage, $sTxtfile) { $sh = curl_init($sHTMLpage); $hFile = FOpen($sTxtfile, "w"); curl_setopt($sh, CURLOPT_FILE, $hFile); curl_setopt($sh, CURLOPT_HEADER, 0); curl_exec ($sh); $sAverageSpeedDownload = curl_getInfo($sh, CURLINFO_SPEED_DOWNLOAD); $sAverageSpeedUpload = curl_getInfo($sh, CURLINFO_SPEED_UPLOAD); echo "
";
 echo "Average speed download == " . $sAverageSpeedDownload . "
"; echo "Average Speed upload == " . $sAverageSpeedUpload . "
"; echo "
"; $aCURLinfo = curl_getInfo($sh); print_r($aCURLinfo); echo "
"; curl_close($sh); FClose ($hFile); echo "(See the file "".$sTxtfile."" in the same path of the hosting". " to where this script PHP).
"; }
Пример 9. Получение страницы через SSL соединение (https)
$ch=curl_init("https://сайт"); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Отключить ошибку "SSL certificate problem, verify that the CA cert is OK" curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // Отключить ошибку "SSL: certificate subject name "hostname.ru" does not match target host name "123.123"" curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); $out=curl_exec($ch); //$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //echo "http_code=".$http_code,", err=".curl_error($ch); curl_close($ch);
Пример 10. Использование сессий и cookie в curl
$cookie_filename=sys_get_temp_dir()+"/cookie.tmp"; $curl=curl_init("http://сайт"); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_filename);//сохранять полученные COOKIE в файл curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_filename); //отсылаем серверу COOKIE полученные от него при авторизации $out=curl_exec($curl);
Пример 11. Отправка файла и многомерный массив в Curl. CURLOPT_POSTFIELDS + CurlFile

Если Вам нужно будет отправить в POST запросе многомерный массив и файл, то вы столкнетесь с неразрешимой проблемой. Если передавать в CURLOPT_POSTFIELDS многомерный массив, то второй уровень будет передан как строка "Array". Если преобразовать с помощью http_build_query, то Вы не сможете передать файл.

Ниже представлена функция кодирования двумерного массива с подгрузкой файлов для Curl, которая будет работать как в старых версиях PHP 5.3, PHP 5.4, так и в PHP 5.6

/** преобразует многомерный массив в одномерный, используйя сложные индексы и заменяет @ в префиксе на CurlFile для испрользоания в Curl * @param $inputArray * @param string $inputKey * @return array $requestVars = array("id" => array(1, 2,"id"=>1234), "name" => "log", "logfile" => "@/tmp/test.log"); получим: ["id"]=> int(1) ["id"]=> int(2) ["id"]=> int(1234) ["name"]=> string(3) "log" ["logfile"]=> string(13) "/tmp/test.log" } */ function convertToStringArray($inputArray, $inputKey="") { $resultArray=; foreach ($inputArray as $key => $value) { $tmpKey = (bool)$inputKey ? $inputKey."[$key]" : $key; if (is_array($value)) { $resultArray+=convertToStringArray($value, $tmpKey); } elseif ($value == "@"){ $resultArray[$tmpKey] = (class_exists(" CURLFile ", false)) ? new CurlFile(ltrim($value, "@")) : $value; } else { $resultArray[$tmpKey] = $value; } } return $resultArray; } // проверяем $requestVars = array("id" => array(1, 2,"id"=>1234), "name" => "log", "logfile" => "@/tmp/test.log"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "сайт"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, convertToStringArray($requestVars)); $res = curl_exec($ch); curl_close($ch); Прикладные примеры использования Curl

Применение libcurl с языками C и Python

Разрабатывать приложения, опирающиеся на протоколы уровня приложений, такие как HTTP и FTP, не очень трудно, но и не тривиально. К тому же такая разработка не находится в центре внимания, поскольку в большинстве случаев гораздо важнее то, что лежит выше этих протоколов. Libcurl как раз и интересен тем, что делает акцент на приложение, а не на преходящий аспект разработки. Отметим, что не многие приложения имеют свой собственный стек TCP/IP – ведь повторное использование всего, что только можно, минимизирует нагрузку на программиста и повышает надежность приложения.

Эта статья начинается с краткого введения в протоколы прикладного уровня, а затем переходит к изучению cURL, libcurl и их применению.

Web-протоколы

Разработка современных приложений существенно отличается от того, что было в недавнем прошлом. Сегодня приложения должны поддерживать связь через сеть или Интернет, предоставляя в распоряжение пользователей сетевой API или интерфейс, а также обеспечивать гибкость посредством пользовательских сценариев. Как правило, современные приложения экспортируют Web-интерфейс с помощью HTTP и передают уведомления о нештатных ситуациях посредством Simple Mail Transport Protocol (SMTP). Эти протоколы позволяют передавать Web-браузеру, работающему в устройстве, конфигурацию или статус и принимать от устройств стандартные сообщения на стандартный клиент электронной почты (соответственно через HTTP и SMTP).

Эти Web-сервисы, как правило, построены поверх уровня сокетов стека сетевых протоколов (рисунок 1). Уровень сокетов реализует API, который восходит к операционной системе Berkeley Software Distribution (BSD) и изолирует детали нижележащих протоколов транспортного и сетевого уровней.

Рисунок 1. Стек сетевых протоколов и libcurl

Web-сервисы обеспечивают взаимодействие между протоколами клиента и сервера. В контексте HTTP сервер – это оконечное устройство, а клиент – браузер в удаленной точке. Для SMTP сервер – это почтовый шлюз или удаленный пользователь, а клиент – оконечное устройство. В некоторых случаях взаимодействие протоколов происходит в два этапа (запрос и ответ), а в других для поддержания связи требуется гораздо больше трафика. Такое взаимодействие может создать значительные трудности, которые преодолеваются с помощью API, таких как libcurl.

Введение в cURL

Происхождение и содержание cURL

cURL предложил Даниель Штенберг, но вклад в разработку внесли свыше 600 программистов. Бесспорно, это полезная технология с широкой областью применения.

Первоначально cURL разработан как средство перемещения файлов между конечными точками с использованием различных протоколов, таких как FTP, HTTP, SCP и другие. Сначала это была утилита командной строки, но теперь это также библиотека с привязками более чем к 30 языкам. Так что теперь, вместо того чтобы использовать cURL из командной строки, можно создавать приложения, которые включают в себя эти важные функции. Библиотека libcurl также переносима и поддерживает Linux®, IBM® AIX®, BSD, Solaris и многие другие варианты UNIX®.

Получение и установка cURL/libcurl

Получить и установить libcurl легко, но процесс зависит от дистрибутива Linux. На Ubuntu эти пакеты можно установить с помощью утилиты apt-get . Две следующие строки показывают, как установить libcurl и Python-привязки для libcurl:

$ sudo apt-get install libcurl3 $ sudo apt-get install python-pycurl

Утилита apt-get гарантирует соблюдение всех зависимостей в процессе установки.

cURL в командной строке

cURL начинался как инструмент командной строки для передачи данных с использованием синтаксиса Uniform Resource Locator (URL). Ввиду популярности этой функции в форме командной строки была создана библиотека для ее интеграции в приложения. Сегодня cURL для командной строки служит оболочкой библиотеки cURL. Эта статья начинается с изучения cURL в командной строке, а затем углубляется в использование этой утилиты в качестве библиотеки.

Две типичных области применения cURL – это передача файлов с использованием протоколов HTTP и FTP. cURL предоставляет простой интерфейс к этим и другим протоколам. Чтобы извлечь файл из Web-сайта с помощью HTTP, достаточно указать cURL имя локального файла, в который нужно записать Web-страницу, а также URL Web-сайта и файл для передачи. Слишком много слов для той простой командной строки, которая приведена в листинге 1.

Листинг 1. Пример использования cURL для извлечения файла с Web-сайта
$ curl -o test html www.exampledomain.com % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 43320 100 43320 0 0 55831 0 --:--:-- --:--:-- --:--:-- 89299 $

Обратите внимание: я указал домен, а не файл, так что получу корневой файл (index.html). Чтобы передать этот файл на сайт FTP с использованием cURL, нужно указать файл для загрузки с опцией -T , а затем ввести URL FTP-сайта и путь к файлу (листинг 2).

Листинг 2. Пример использования cURL для загрузки файла на FTP-сайт
$ curl -T test.html ftp://user:[email protected]/ftpdir/ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 43320 0 0 100 43320 0 38946 0:00:01 0:00:01 --:--:-- 124k $

Бывает ли проще? Достаточно освоить несколько простых моделей, и cURL окажется предельно простым в применении. Но многообразие имеющихся опций очень велико – запрос помощи из командной строки cURL (--help) выводит 129 строк. Большое число опций позволяет управлять всем – от многословия до безопасности и различных зависящих от протокола настраиваемых элементов.

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

cURL как библиотека

Если вы наблюдали за языками сценариев на протяжении последних 10 лет, то заметили явные изменения в их составе. Такие языки сценариев, как Python, Ruby, Perl и многие другие включают не только уровень сокетов, как C или C++, но и интерфейсы протокола прикладного уровня. Эти языки сценариев содержат высокоуровневые функции, которые делают тривиальным, например, создание сервера или клиента HTTP. Библиотека libcurl добавляет функциональность, схожую с такими языками, как C и C++, но таким образом, что можно работать с множеством языков. Libcurl примерно одинаково ведет себя во всех языках, которые поддерживает, хотя, так как эти языки могут значительно различаться (C и Scheme), могут различаться и способы обеспечения этого поведения.

Библиотека libcurl включает в себя функции, которые иллюстрируются в листингах и , в форме API, поэтому ее можно использовать в высокоуровневых языках (на сегодняшний день более 30). В этой статье представлены два примера применения libcurl. Первый исследует простой клиент HTTP на языке C (подходит для создания Web-пауков), а второй представляет собой простой клиент HTTP на Python.

HTTP-клиент на языке С

API для C обеспечивает два API поверх функциональности libcurl. Простой интерфейс – это простой синхронный API (т. е. при обращении к libcurl с запросом она выполняет его до конца или до сообщения об ошибке). Мультиинтерфейс обеспечивает контроль над libcurl, позволяя приложению выполнять несколько одновременных передач и управлять тем, куда и когда libcurl переносит данные.

В этом примере используется простой интерфейс. Этот API все же предоставляет некоторый контроль над процессом перемещения данных (с использованием функций обратного вызова), но при этом соответствует своему названию. В листинге 3 приводится пример на языке С для HTTP.

Листинг 3. Клиент HTTP на языке С с использованием простого интерфейса libcurl
#include #include #include #define MAX_BUF 65536 char wr_buf; int wr_index; /* * Write data callback function (called within the context of * curl_easy_perform. */ size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { int segsize = size * nmemb; /* Check to see if this data exceeds the size of our buffer. If so, * set the user-defined context value and return 0 to indicate a * problem to curl. */ if (wr_index + segsize > MAX_BUF) { *(int *)userp = 1; return 0; } /* Copy the data from the curl buffer into our buffer */ memcpy((void *)&wr_buf, buffer, (size_t)segsize); /* Update the write index */ wr_index += segsize; /* Null terminate the buffer */ wr_buf = 0; /* Return the number of bytes received, indicating to curl that all is okay */ return segsize; } /* * Simple curl application to read the index.html file from a Web site. */ int main(void) { CURL *curl; CURLcode ret; int wr_error; wr_error = 0; wr_index = 0; /* First step, init curl */ curl = curl_easy_init(); if (!curl) { printf("couldn"t init curl\n"); return 0; } /* Tell curl the URL of the file we"re going to retrieve */ curl_easy_setopt(curl, CURLOPT_URL, "www.exampledomain.com"); /* Tell curl that we"ll receive data to the function write_data, and * also provide it with a context pointer for our error return. */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&wr_error); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); /* Allow curl to perform the action */ ret = curl_easy_perform(curl); printf("ret = %d (write_error = %d)\n", ret, wr_error); /* Emit the page if curl indicates that no errors occurred */ if (ret == 0) printf("%s\n", wr_buf); curl_easy_cleanup(curl); return 0; }

В верхней части расположены необходимые файлы include , в том числе корневой файл cURL. Далее я определил пару переменных для передачи. Первая, wr_buf , представляет собой буфер, в который будут записываться входные данные. wr_index отражает индекс текущей записи буфера.

Опустимся к функции main , которая выполняет установку с помощью простого API. Все вызовы cURL проходят через указатель, который хранит состояние конкретного запроса. Он определен как CURL pointer reference. Этот пример создает также специальный возвратный код, называемый CURLcode . Перед использованием любых функций libcurl нужно вызывать curl_easy_init , чтобы получить указатель CURL . Далее обратите внимание на несколько вызовов функции curl_easy_setopt . Это настройки указателей для конкретной операции. Для этих вызовов вводится указатель, команда и опция. Сначала в этом примере применяется оператор CURLOPT_URL для задания URL извлекаемых данных. Затем следует CURL_WRITEDATA для создания контекстной переменной (в нашем случае это внутренняя переменная записи ошибок). Наконец, CURLOPT_WRITEFUNCTION определяет функцию, которую нужно вызвать при наличии данных. API вызовет эту функцию один или несколько раз с данными, считанными им после сигнала запуска.

Чтобы начать передачу, вызовите функцию curl_easy_perform . Ее задача заключается в выполнении передачи с учетом предварительно заданной конфигурации. При вызове этой функции она возвращает результат только после успешной передачи или ошибки. Последние элементы main предназначены для передачи возвращаемых статусов, запуска чтения страницы и, наконец, для очистки с помощью функции curl_easy_cleanup (по завершении операции).

Теперь рассмотрим функцию write_data . Эта функция обратного вызова, которая вызывается, когда данные по конкретной операции получены. Обратите внимание, что когда данные считываются с Web-сайта, они записываются к вам (write_data). Обратный вызов содержит буфер (с готовыми данными), число элементов и их размер (их произведение дает общий объем данных в буфере), а также указатель контекста. Первая задача заключается в том, чтобы обеспечить достаточную емкость буфера (wr_buf) для записи данных. В противном случае он устанавливает указатель контекста и возвращает ноль, что указывает на наличие проблемы. Иначе, он копирует данные из буфера cURL в ваш буфер и наращивает индекс, указывая на следующее место для записи. В этом примере строка завершается, так что впоследствии к нему можно применить printf . Наконец, он возвращает в libcurl количество обработанных байтов. Это говорит libcurl о том, что данные приняты, и их можно удалить. Вот и все – не правда ли, простой способ считать файл с Web-сайта в память?

HTTP-клиент на Python

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

Код простого HTTP-клиента, написанный на языке Python с использованием pycurl , приведен в листинге 4.

Листинг 4. HTTP-клиент на Python с использованием интерфейса pycurl из libcurl
import sys import pycurl wr_buf = "" def write_data(buf): global wr_buf wr_buf += buf def main(): c = pycurl.Curl() c.setopt(pycurl.URL, "http://www.exampledomain.com") c.setopt(pycurl.WRITEFUNCTION, write_data) c.perform() c.close() main() sys.stdout.write(wr_buf)
Создание прототипа на Python

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

Этот код значительно проще, чем версия на C. Он начинается с импортирования необходимых модулей (стандартного системного модуля sys и модуля pycurl). Далее определяется буфер записи (wr_buf). Как и в программе на C, я декларирую функцию write_data . Обратите внимание, что эта функция принимает один аргумент: буфер данных, считанных с сервера HTTP. Я просто взял этот буфер и добавил его к глобальному буферу записи. Функция main начинает с создания указателя Curl , затем использует для записи методы setopt для определения URL и WRITEFUNCTION . Она вызывает метод perform для запуска передачи и закрывает указатель. Наконец, она вызывает функцию main и передает буфер записи в stdout . Обратите внимание, что в данном случае указатель ошибки контекста не нужен, поскольку используется конкатенация строк Python, а значит, не нужно использовать строку со статически заданным размером.

Что дальше

Эта статья лишь "скребет по поверхности" libcurl, учитывая огромное количество протоколов и языков, поддерживаемых библиотекой. Но, надеюсь, она демонстрирует, как легко создавать приложения, использующие протоколы уровня приложений, такие как HTTP. Web-сайт libcurl (см. раздел ) содержит большое количество примеров и значительный объем полезной документации. Поэтому в следующий раз при разработке Web-браузера, спайдера или другого приложения, которому требуется протокол уровня приложения, попробуйте libcurl. Это наверняка ускорит процесс разработки, и вы получите от него удовольствие.

Это руководство предназначено для тех web-разработчиков, которые хотят автоматизировать передачу файлов по сети либо взаимодействовать с другими Интернет - сервисами. Для чтения этой главы вам необходимо владеть пониманием принципа работы стратегии клиент - сервер и знать основы синтаксиса PHP.

cURL и libcurl - библиотеки, позволяющие серверу передавать файлы на удаленный компьютер, используя множество Интернет протоколов. Библиотеки имеют очень гибкую настройку и позволяют выполнить практически любой удаленный запрос. Используя их, web-сервер может выступать полноценным клиентом любого основанного на HTTP протоколе сервисе, к примеру: XML-RPC, SOAP, или WebDAV.

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

Что такое cURL и libcurl

cURL является сокращением от "Client URLs". Он был разработан Daniel Stenberg в 1998 году как утилита, работающая из командной строки. Libcurl - переносимая библиотека, предоставляющая простой API-интерфейс к функциональности cURL. Библиотека безопасна в мультипоточной среде, совместима с IPv6 и поддерживает постоянные соединения. Интерфейс взаимодействия с php был добавлен Sterling Hughes.

cURL и libcurl могут использоваться для передачи информации с использованием таких протоколов, как HTTPS, FTP, FTPS, GOPHER, LDAP, DICT, TELNET и FILE. Реализована поддержка практически всех *nix систем, а также Windows, OS/2, BeOS и некоторых других.

Библиотека curl - Open Source продукт с оригинальной MIT/X лицензией, позволяющей использовать этот пакет в любых: как коммерческих, так и некоммерческих целях, включать ее в свой дистрибутив (даже если он распространяется без открытого исходного кода).

Необходимо понимать, что cURL не имеет ничего общего с Curl Corporation, являющейся коммерческим производителем языка программирования Curl.

Инсталляция cURL

Для работы в PHP версии 4.2.3 и выше вам необходим cURL версии не ниже 7.9.0. Для работы в PHP версии 4.3.0 и выше вам необходим cURL версии не ниже 7.9.8.

Windows

Как и любой другой дополнительный модуль, он требует проинсталлированного дистрибутива PHP. Для установки cURL скопируйте файлы php4ts.dll, ssleay32.dll, php_curl.dll, msvcrt.dll из каталога DLL в системную директорию Windows, как правило, это:

C:\windows\system для Windows 9x/Me c:\winnt\system32 для Windows NT/2000 c:\windows\system32 для Windows XP.

После этого необходимо раскомментировать строку

;extension=php_curl.dll

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

dl ("php_curl.dll" );
?>

Unix

Ближайшее зеркало, содержащее исходные коды и откомпилированные бинарные файлы для различных операционных систем, вы можете найти на сайте http://curl.haxx.se/ .

Поскольку cURL использует библиотеку openssl для SSL соединений, вначале необходимо установить на север SSL. В случае, если при инсталляции cURL библиотека openssl найдена не будет, произойдет установка cURL без поддержки SSL соединений.

Инсталляция cURL состоит из следующих шагов: ./configure, make, make install.

После этого необходимо пересобрать PHP c опцией --with-curl

О том, включена ли поддержка cURL в php, вы можете узнать, выполнив phpinfo().

Пример использования cURL

Использование cURL из командной строки очень просто. Следующий пример запрашивает web-страницу и выводит ее в stdout

$ curl -L zend.com

M(опция -L разрешает переадресации)

Также возможно использование cURL из командной строки при помощи PHP. Следующий пример запрашивает 3 страницы и выводит их на экран

$var = echo shell_exec ("/usr/bin/curl -L http://www.zend.com http://zend.com/developers.php http://zend.com/zend/tut/" );
?>

Пример использования cURL в PHP

Использование libcurl в php-скрипте является достаточно простым, особенно для таких операций, как генерация POST-запросов.

Для использования libcurl необходимо выполнить следующие шаги:

  • Инициализировать сессию cURL
  • Установить опции cURL (порядок установки опций не имеет значения)
  • Выполнить запрос
  • Завершить сессию cURL

Для демонстрации вышеперечисленного приведем практические примеры использования cURL для генерации POST-запроса, HTTP-авторизации, FTP-сессии.

// Поиск книг на сервере amazon.com
$url = "http://www.amazon.com/exec/obidos/search-handle-form/002-5640957-2809605" ;
$ch = curl_init ();
// set url to post to
curl_setopt ($ch , CURLOPT_FAILONERROR , 1 );
curl_setopt ($ch , CURLOPT_FOLLOWLOCATION , 1 ); // allow redirects
// return into a variable
curl_setopt ($ch , CURLOPT_TIMEOUT , 3 ); // times out after 4s
curl_setopt ($ch , CURLOPT_POST , 1 ); // set POST method
curl_setopt ($ch , CURLOPT_POSTFIELDS , "url=index%3Dbooks&field-keywords=PHP+MYSQL" ); // add POST fields
$result = curl_exec ($ch ); // run the whole process
curl_close ($ch );
echo $result ;
?>

// HTTP authentication
$url = "http://www.example.com/protected/" ;
$ch = curl_init ();
curl_setopt ($ch , CURLOPT_RETURNTRANSFER , 1 );
curl_setopt ($ch , CURLOPT_URL , $url );
curl_setopt ($ch , CURLOPT_USERPWD , "myusername:mypassword" );
$result = curl_exec ($ch );
curl_close ($ch );
echo $result ;
?>

// FTP this script to a server
$fp = fopen (__FILE__ , "r" );
$url = "ftp://username:[email protected]:21/path/to/newfile.php" ;
$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_FTPASCII , 1 );
curl_setopt ($ch , CURLOPT_INFILESIZE , filesize (__FILE__ ));
$result = curl_exec ($ch );
curl_close ($ch );
?>

При возникновении проблем в использовании cURL необходимо добавить следующие строки перед вызовом curl_close для получения отчета о последнем выполненном запросе:

print_r (curl_getinfo ($ch ));
echo "\n\ncURL error number:" . curl_errno ($ch );
echo "\n\ncURL error:" . curl_error ($ch );
// ...close cURL handle ($ch) below
?>

Решение о том, что использовать: cURL или libcurl, - стоит принимать в зависимости от обстоятельств. В случае, если Вы пишете выполняемый из командной строки скрипт, либо у Вашего провайдера нет поддержки libcurl, имеет смысл использовать cURL. В остальных случаях использование libcurl оказывается более удобным.




Есть еще вопросы или что-то непонятно - добро пожаловать на наш

Эта статья предполагает, что вам известны основы построения сетей и язык HTML.

Возможность написания скриптов является существенной при построении хорошей компьютерной системы. Расширяемость возможностей Unix-систем при помощи shell-скриптов и различных программ, выполняющих автоматизированные команды - вот одна из причин того, почему они имеют такой успех.

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

Curl - инструмент командной строки, который позволяет проделывать URL-манипуляции и передачи различного рода. Эта статья сфокусирована на создании простых HTTP-запросов. Предполагается, что вы уже знаете где набирать

# curl --help

# curl --manual

для получения информации о curl.

Curl не является инструментом, который будет делать все за вас. Он создает запросы, принимает данные и отсылает данные. Возможно, вам потребуется какой-то "клей" для объединения всего, возможно какой-то скриптовый язык (например bash) или несколько ручных вызовов.

1. Протокол HTTP

HTTP - это протокол, используемый при приеме данных от web-серверов. Это очень простой протокол, который построен на TCP/IP. Протокол также позволяет отправлять информацию на сервер от клиента, используя несколько методов, как будет показано далее.

HTTP - это строки ASCII-текста, отсылаемые от клиента к серверу для запроса какого-либо действия. При получении запроса сервер отвечает клиенту несколькими служебными текстовыми строками, а затем и собственно контентом.

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

2. URL

Формат URL (Uniform Resource Locator - универсальный адрес ресурса) задает адрес определенного ресурса в Интернете. Вам это наверняка известно, примеры URL: http://curl.haxx.se или https://yourbank.com.

3. Получить (GET) страницу

Простейший и самый обычный HTTP-запрос - получить содержимое URL. URL может ссылаться на web-страницу, картинку или файл. Клиент отсылает GET-запрос на сервер и получает запрашиваемый документ. Если выполнить команду

# curl http://curl.haxx.se

вы получите web-страницу, выведенную в ваше терминальное окно. Полный HTML-документ, который содержится по этому адресу URL.

Все HTTP-ответы содержат набор заголовков, которые обычно скрыты. Чтобы их увидеть вместе с самим документом, используйте ключ curl -i. Вы можете также запросить только заголовки при помощи ключа -I (который заставит curl сделать HEAD-запрос).

4. Формы

Формы - основной способ представления web-сайта как HTML-страницы с полями, в которые пользователь вводит данные, и затем нажимает на кнопку "OK" или "Отправить", после чего данные отсылаются на сервер. Затем сервер использует принятые данные и решает, как действовать дальше: искать информацию в базе данных, показать введенный адрес на карте, добавить сообщение об ошибке или использовать информацию для аутентификации пользователя. Разумеется, на стороне сервера имеется какая-то программа, которая принимает ваши данные.

4.1 GET

GET-форма использует метод GET, например следующим образом:

Если вы откроете этот код в вашем браузере, вы увидите форму с текстовым полем и кнопку с надписью "OK". Если вы введете "1905" и нажмете OK, браузер создаст новый URL, по которому и проследует. URL будет представляться строкой, состоящей из пути предыдущего URL и строки, подобной "junk.cgi?birthyear=1905&press=OK".

Например, если форма располагалась по адресу "www.hotmail.com/when/birth.html", то при нажатии на кнопку OK вы попадете на URL "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK".

Большинство поисковых систем работают таким образом.

Чтобы curl сформировал GET-запрос, просто введите то, что ожидалось от формы:

# curl "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK"

4.2 POST

Метод GET приводит к тому, что вся введенная информация отображается в адресной строке вашего браузера. Может быть это хорошо, когда вам нужно добавить страницу в закладки, но это очевидный недостаток, когда вы вводите в поля формы секретную информацию, либо когда объем информации, вводимый в поля, слишком велик (что приводит к нечитаемому URL).

Протокол HTTP предоставляет метод POST. С помощью него клиент отправляет данные отдельно от URL и поэтому вы не увидете их в адресной строке.

Форма, генерирующая POST-запрос, похожа на предыдущую:

Curl может сформировать POST-запрос с теми же данными следующим образом:

# curl -d "birthyear=1905&press=%20OK%20" www.hotmail.com/when/junk.cgi

Этот POST-запрос использует "Content-Type application/x-www-form-urlencoded", это самый широко используемый способ.

Данные, которые вы отправляете к серверу, должны быть правильно закодированы, curl не будет делать это за вас. К примеру, если вы хотите, чтобы данные содержали пробел, вам нужно заменить этот пробел на %20 и т.п. Недостаток внимания к этому вопросу - частая ошибка, из-за чего данные передаются не так, как надо.

В далеком 1995 был определен дополнительный способ передавать данные по HTTP. Он задокументирован в RFC 1867, поэтому этот способ иногда называют RFC1867-posting.

Этот метод в основном разработан для лучшей поддержки загрузки файлов. Форма, которая позволяет пользователю загрузить файл, выглядит на HTML примерно следующим образом:

Заметьте, что тип содержимого Content-Type установлен в multipart/form-data.

Чтобы отослать данные в такую форму с помощью curl, введите команду:

# curl -F upload=@localfilename -F press=OK

4.4 Скрытые поля

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

Простой пример формы с одним видимым полем, одним скрытым и кнопкой ОК:

Чтобы отправить POST-запрос с помощью curl, вам не нужно думать о том, скрытое поле или нет. Для curl они все одинаковы:

# curl -d "birthyear=1905&press=OK&person=daniel"

4.5 Узнать, как выглядит POST-запрос

Когда вы хотите заполнить форму и отослать данные на сервер с помощью curl, вы наверняка хотите, чтобы POST-запрос выглядел точно также, как и выполненный с помощью браузера.

Простой способ увидеть свой POST-запрос, это сохранить HTML-страницу с формой на диск, изменить метод на GET, и нажать кнопку "Отправить" (вы можете также изменить URL, которому будет передаваться данные).

Вы увидите, что данные присоединились к URL, отделенные символами "?", как и предполагается при использовании GET-форм.

5. PUT

Пожалуй, лучший способ загружать данные на HTTP-сервер, это использовать PUT. Опять же, это требует программы (скрипта) на серверной части, которая знает, что делать и как принимать поток HTTP PUT.

Отослать файл на сервер при помощи curl:

# curl -T uploadfile www.uploadhttp.com/receive.cgi

6. Аутентификация

Аутентификация - передача серверу имени пользователя и пароля, после этого он проверяет, имеете ли вы право выполнить требуемый запрос. Аутентификация по методу Basic (которым curl пользуется по умолчанию) основана на открытом тексте, что означает, что имя пользователя и пароль не будут зашифрованы, а лишь слегка "затуманены" по алгоритму Base64, что оставляет возможность узнать эту информацию злоумышленникам на пути между вами и HTTP-сервером.

Указание curl использовать имя пользователя и пароль:

# curl -u name:password www.secrets.com

Сайт может требовать использования другого метода аутентификации (посмотрите, что пишет сервер в заголовках), в этих случаях можно использовать ключи --ntlm, --digest, --negotiate или даже --anyauth. Иногда доступ к внешним HTTP-серверам происходит через прокси, так часто делают в компаниях и фирмах. HTTP-прокси может требовать свои логин и пароль для доступа к Интернету. Соответствующий ключ curl:

# curl -U proxyuser:proxypassword curl.haxx.se

Если прокси требует аутентификации по методу NTLM, укажите --proxy-ntlm, если метод Digest, то --proxy-digest.

Если вы не укажете пароль в ключах -u и -U, то curl спросит его у вас в интерактивном режиме.

Заметьте, что когда curl работает, строка запуска (а вместе с этим и ключи, и пароли) могут быть видны другим пользователям вашей системы в списке задач. Есть способы предотвратить это. Об этом ниже.

7. Referer

HTTP-запрос может включать поле "referer", которое указывает, с какого URL пользователь пришел на данный ресурс. Некоторые программы/скрипты проверяют поле "referer" и не выполняют запрос, если пользователь пришел с неизвестной страницы. Хотя это и глупый способ проверки, тем не менее многие скрипты используют его. С помощью curl вы можете вписать что угодно в поле "referer" и таким образом заставлять выполнять то, что вам нужно.

Это делается следующим образом:

# curl -e http://curl.haxx.se daniel.haxx.se

8. User Agent

Все HTTP-запросы поддерживают поле "User-Agent", в котором указывается клиентское приложение пользователя. Многие web-приложения используют эту информацию, чтобы тем или иным способом отобразить страницу. Web-программисты создают несколько версий страницы для пользователей разных браузеров в целях улучшения внешнего вида, использования различных скриптов javascript, vbscript и т.д.

Иногда вы можете обнаружить, что curl возвращает страницу не такой, какой вы ее видели в своем браузере. В этом случае как раз уместно использовать поле "User Agent", чтобы в очередной раз обмануть сервер.

Замаскировать curl под Internet Explorer на машине с Windows 2000:

# curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"

Почему бы не стать Netscape 4.73 на Linux-машине (PIII):

# curl -A "Mozilla/4.73 (X11; U; Linux 2.2.15 i686)"

9. Перенаправления (redirects)

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

По умолчанию curl не идет по адресу, указанному в "Location:", а просто показывает страницу как обычно. Но можно его направить следующим образом:

# curl -L www.sitethatredirects.com

Если вы используете curl для POST-запросов на сайт, который сразу же перенаправляет на другую страницу, вы можете смело использовать связку -L и -d/-F. Curl сформирует POST-запрос для первой страницы, а затем GET-запрос для последующей.

10. Cookies

С помощью cookies веб-браузеры контролируют состояние на стороне клиента. Cookie - это имя с присоединенным содержимым. Сервер при помощи отправки cookies сообщает клиенту путь и имя хоста, по которому в следующий раз должны быть отправлены cookies, сообщает время жизни cookies и некоторые другие параметры.

Когда клиент соединяется с сервером по адресу, указанному в принятом cookie, клиент посылает этот cookie к серверу (если время жизни не истекло).

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

Простейший способ отправить cookie к серверу при получении страницы с помощью curl, это добавить соответствующий ключ в командной строке:

# curl -b "name=Daniel" www.cookiesite.com

Cookies отправляются как обычные HTTP-заголовки. Это позволяет curl сохранять cookies, сохраняя заголовки. Сохранение cookies с помощью curl выполняется командой:

# curl -D headers_and_cookies www.cookiesite.com

(кстати, для сохранения cookies лучше использовать ключ -c, об этом ниже).

У curl имеется полнофункциональный обработчик cookies, который полезен, когда вы хотите соединиться в очередной раз к серверу и использовать cookies, сохраненные в прошлый раз (либо подработанные вручную). Для использования cookies, сохраненных в файле, вызовите curl так:

# curl -b stored_cookies_in_file www.cookiesite.com

"Cookie-движок" curl включается, когда вы указываете ключ -b. Если вы хотите, чтобы curl лишь воспринимал cookies, используйте -b с указанием файла, которого не существует. Например, если вы хотите, чтобы curl принял cookies со страницы, а затем пошел по перенаправлению (возможно, отдав принятый только что cookie), то можно вызывать curl так:

# curl -b nada -L www.cookiesite.com

Curl умеет читать и писать cookie-файлы, имеющие формат Netscape и Mozilla. Это удобный способ обмениваться cookies между браузерами и автоматическими скриптами. Ключ -b автоматически определяет, является ли данный файл cookie-файлом указанных браузеров и обрабатывает его соответствующим образом, а используя ключ -c/--cookie-jar, вы можете заставить curl записать новый cookie-файл по завершении операции:

# curl -b cookies.txt -c newcookies.txt www.cookiesite.com

11. HTTPS

Есть несколько способов обезопасить ваши HTTP-передачи. Наиболее известным протоколом, решающим эту задачу, является HTTPS, или HTTP over SSL. SSL зашифровывает все посылаемые и принимаемые по сети данные, что увеличивает вероятность того, что ваша информация останется в тайне.

Curl поддерживает запросы к HTTPS-серверам благодаря свободно распространяемой библиотеке OpenSSL. Запросы происходят обычным способом:

# curl https://that.secure.server.com

11.1 Сертификаты

В мире HTTPS для аутентификации в дополнение к имени пользовавателя и паролю вы используете сертификаты. Curl поддерживает сертификаты на стороне клиента. Все сертификаты заперты ключевой фразой, которую вам нужно ввести прежде чем curl может начать с ними работу. Ключевая фраза может быть указана либо в командной строке, либо введена в интерактивном режиме. Сертификаты в curl используются следующим образом:

# curl -E mycert.pem https://that.secure.server.com

Curl также проверяет сервер на подлинность, сверяя сертификат сервера с локально хранящимся. Обнаружившееся несоответствие приведет к тому, что curl откажется соединяться. Для игнорирования проверки на подлинность используйте ключ -k.

Более подробная информация о сертификатах может быть найдена на странице http://curl.haxx.se/docs/sslcerts.html.

12. Произвольные заголовки запроса

Возможно, вам понадобится изменять или добавлять элементы отдельных запросов curl.

К примеру, вы можете изменить запрос POST на PROPFIND и отправить данные как "Content-Type: text/xml" (вместо обычного Content-Type):

# curl -d "" -H "Content-Type: text/xml" -X PROPFIND url.com

Вы можете удалить какой-нибудь заголовок, указав его без содержимого. Например, вы можете удалить заголовок "Host:", тем самым сделав запрос "пустым":

# curl -H "Host:" http://mysite.com

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

# curl -H "Destination: http://moo.com/nowhere" http://url.com

13. Отладка

Часто бывает так, что сайт реагирует на запросы curl не так, как на запросы браузера. В этом случае нужно максимально уподобить curl браузеру:

  • Используйте ключ --trace-ascii для сохранения подробного отчета запросов, чтобы затем подробно изучить их и разобраться в проблеме.
  • Убедитесь, что вы проверяете на cookies и используете их при необходимости (ключ чтения -b и сохранения -c)
  • Укажите в поле "user-agent" один из последних популярных браузеров
  • Заполните поле "referer" как это делает браузер
  • Если вы используете POST-запросы, убедитесь, что все поля передаются в том же порядке, что и браузер (см. выше, пункт 4.5)

Хороший помощник в этом нелегком деле - плагин для Mozilla/Firefox LiveHTTPHeader, который позволяет просматривать все заголовки, которые отправляет и принимает этот браузер (даже при использовании HTTPS).

Более низкоуровневый подход - захват HTTP-траффика в сети с помощью программ, таких как ethereal или tcpdump, с последующим анализом, какие заголовки были получены и отправлены браузером (HTTPS делает этот подход неэффективным).

RFC 2616 обязательно для чтения всем, кто хочет понять протокол HTTP.

RFC 2396 объясняет синтаксис URL.

RFC 2109 определяет работу cookies.

RFC 1867 определяет формат File Upload Post.

http://openssl.planetmirror.com - домашняя страница проекта OpenSSL

http://curl.haxx.se - домашняя страница проекта cURL