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

Источник: «10 Examples Why cURL is an Awesome CLI Tool»
Независимо от того, разработчик ли вы, DevOps-инженер, системный администратор, QA или представитель любой другой технической профессии, вы наверняка знакомы с cURL — инструментом командной строки и библиотекой для передачи данных с помощью URL (как описано в документации).

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

И в этой статье рассмотрим именно такие крутые примеры и трюки, демонстрирующие, почему curl является удивительным и недооценённым инструментом…

Глоббинг

Во-первых, глоббинг, позволят выполнять несколько запросов с помощью одной команды curl:

curl -s "https://jsonplaceholder.typicode.com/users/[1-3]" | jq -s .
curl -s "https://jsonplaceholder.typicode.com/users/[0-10:2]" | jq -s .

curl -s "https://jsonplaceholder.typicode.com/photos/{1,6,35}" | jq -s .

curl -s "https://jsonplaceholder.typicode.com/users/[1-3]" -o "file_#1.json"

Первые две команды показывают, как можно выполнить ряд запросов — первая команда производит запросы к .../users/1, .../users/2 и .../users/3, а вторая использует опцию step, что даёт 2, 4, 6, 8 и 10. Учитывая, что эти конкретные запросы возвращают JSON, объединим их с jq ... с помощью оператора -s (slurp), объединяющего ответы отдельных запросов в единый массив.

В третьем примере вместо диапазона используется список конкретных чисел — это также работает для символов и слов — например, можно использовать группировку для выполнения запросов с несколькими протоколами: {http,https}://...

Последний пример сочетает глоббинг и выходные переменные, где переменная #1 в имени файла ссылается на диапазон [1-3]. В результате будут созданы файлы file_1.json, file_2.json и file_3.json.

Конфигурационные файлы

Чаще всего при использовании curl необходимо передавать одни и те же параметры командной строки, такие как настройки прокси, таймауты запросов, заголовки и т.д. Именно здесь может пригодиться конфигурационный файл curl с именем .curlrc:

# ~/.curlrc

# some headers
-H "Upgrade-Insecure-Requests: 1"
-H "Accept-Language: en-US,en;q=0.8"

# follow redirects
--location

Это просто текстовый файл, где каждая строка представляет собой одну опцию, которая будет передана curl. Он автоматически считывается из ~/.curlrc, поэтому не нужно никаких дополнительных флагов, но можно использовать -K, чтобы переопределить или указать другое местоположение, например:

curl -K .curlrc https://google.com

Аналогично флагам и опциям, можно передать учётные данные. Это можно сделать с помощью опции --user, но тогда учётные данные останутся в истории командной строки, поэтому вместо этого лучше использовать файл .netrc, поддерживаемый curl:

# ~/.netrc
machine https://authenticationtest.com/HTTPAuth/
login user
password pass

Формат включает machine (URL), login и password — они могут быть в одной строке или как показано выше, также можно разместить записей несколько в одном файле. Для использования просто передайте его в curl, например:

curl --netrc-file .netrc https://authenticationtest.com/HTTPAuth/

Параллельные запросы

О диапазонах запросов уже говорилось в разделе глоббинг, но как насчёт распараллеливания? Ну, curl может сделать и это:

curl -I --parallel --parallel-immediate --parallel-max 3 --config websites.txt

curl -I --parallel --parallel-immediate --parallel-max 3 stackoverflow.com google.com example.com

Всё, что нужно сделать, это добавить --parallel (или -Z), и curl будет открывать до 50 параллельных соединений (можно изменить с помощью --parallel-max N). Также обратите внимание на то, как указывается URL — первая опция --config и текстовый файл, выглядящий следующим образом:

url = "stackoverflow.com"
url = "google.com"
url = "example.com"

Другой вариант — просто передать все URL в командную строку. Оба варианта также работают с непараллельными запросами!

Форматирование и переменные

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

curl --silent --output /dev/null --show-error -w @format.txt http://example.com/

# Type: text/html; charset=UTF-8
# Code: 200
#
# From 8.1.0:
# Scheme: http
# Host: example.com
# Port: 80
#
# Read header content (v7.83.0):
# Server: Sat, 29 Jun 2024 13:01:30 GMT

Для этого используется опция -w и передаётся формат файла. Чтобы получить такой результат, как показано выше, можно использовать:

# format.txt
Type: %{content_type}\nCode: %{response_code}\n\n

From 8.1.0:\n\n

Scheme: %{url.scheme}\n
Host: %{url.host}\n
Port: %{url.port}\n

Read header content (v7.83.0):\n
%header{date}

Каждая переменная заключена в %{...}. Они могут быть как простыми, например response_code, так и частью url.<NAME>, ссылающейся на компоненты URL, такие, как хост или порт. Наконец, можно вывести заголовки ответа с помощью переменных %header{HEADER_NAME}.

Одним из многих удобных случаев использования форматирования является измерение времени запроса/ответа, что можно сделать с помощью следующего формата:

# format.txt
time_namelookup: %{time_namelookup}s\n
time_connect: %{time_connect}s\n
time_appconnect: %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect: %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
----------\n
time_total: %{time_total}s\n

# Результат:
time_namelookup: 0.000765s
time_connect: 0.111908s
time_appconnect: 0.000000s
time_pretransfer: 0.111967s
time_redirect: 0.000000s
time_starttransfer: 0.223373s
----------
time_total: 0.223992s

Полный список переменных см. в документации.

Тестирование и диагностика неполадок

Чаще всего curl используется для диагностики (сетевых) неполадок — зачастую простого запроса к определённому URL достаточно для получения информации, но есть и другие возможности, например, можно заставить использовать определённый локальный сетевой интерфейс:

ip link show
# ...
# 3: wlp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT group default qlen 1000

curl --interface wlp5s0 https://example.com

Аналогичным образом можно принудительно установить определённый DNS-сервер:

curl --dns-ipv4-addr 1.1.1.1 https://example.com

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

curl --connect-timeout 30 --silent --output /dev/null \
--show-error -w 'Total: %{time_total}s\n' http://google.com/ || EXIT_CODE=$?

if [ $EXIT_CODE = 28 ]
then
echo "Cannot connect (Timeout)."
else
echo "Can connect."
fi

Это может быть удобно, например, для проверки работы прокси-сервера (с помощью -x http://proxy.example.com:80).

trurl

curl — это не просто CLI-инструмент: в проект входит libcurl, а также trurl, который с удовольствием продемонстрирую здесь.

trurl — это специализированный инструмент для разбора URL-адресов, являющийся родственным проектом curl. Его можно установить из исходных текстов:

sudo apt-get install libcurl4-openssl-dev
git clone https://github.com/curl/trurl.git
cd trurl
make
# ...

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

trurl --url https://example.com/some/path/to/file.html --get '{path}'
# /some/path/to/file.html

trurl --url "https://example.com/?name=hello" --append query=key=value
# https://example.com/?name=hello&key=value

# Parse as JSON:
./trurl --url "https://example.com/?name=hello" --json
# [
# {
# "url": "https://example.com/?name=hello",
# "parts": {
# "scheme": "https",
# "host": "example.com",
# "path": "/",
# "query": "name=hello"
# },
# "params": [
# {
# "key": "name",
# "value": "hello"
# }
# ]
# }
# ]

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

Второй использует функцию append, чтобы добавить параметр запроса в URL.

И последний пример демонстрирует опцию --json, выводящую разобранный URL в формате JSON, который отлично подходит для дальнейшей обработки.

trurl может многое другое — вы можете посмотреть это видео или руководство (примеры внизу).

Отправка/загрузка данных

Чаще всего curl используется для скачивания или запроса данных, но он также может (очевидно) отправлять данные. В отправке данных с помощью curl нет ничего нового, верно?

curl -X POST "https://httpbin.org/post" -H "accept: application/json" --json '{"key": "value"}'

Но отправка JSON в таком виде с необходимостью чередовать одинарные и двойные кавычки быстро надоедает, есть лучший способ:

jo -p key=value | curl -X POST "https://httpbin.org/post" -H "accept: application/json" --json @-

Думаю, все знакомы с разбором JSON-вывода curl с помощью jq, но как насчёт обратного? — Выше был использован инструмент jo, легко создающий JSON, который можно передать в curl с помощью опции --json.

Естественно, опция --json может также принимать данные из файла, например, с помощью --json @data.json.

Протоколы

И последнее, но не менее важное, это протоколы — обычно используются только HTTP или HTTPS, но curl поддерживает множество протоколов.

В частности, хочу упомянуть telnet, удобный для проверки того, слушает ли сервер определённый порт, но что делать, если на сервере/машине отсутствует и нет возможности установить telnet? Просто используйте curl:

# То же самое, что telnet example.com 1234
curl telnet://example.com:1234

Некоторые из наиболее странных (забавных) вариантов протоколов — IMAP, POP3 и SMTP для электронной почты, что означает, что можно читать и отправлять письма с помощью curl. Чтобы прочитать их:

curl --url "imaps://imap.gmail.com:993/Inbox;UID=1" --user "user@gmail.com:PASSWORD"

Чтобы это работало именно с GMail, необходимо создать пароль приложения, который менее надёжным, чем обычный пароль. Если действительно хотите попробовать, ознакомьтесь с Gmail IMAP документацией и этими запросами для вдохновения.

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

curl smtp://mail.example.com \
--mail-from me@example.com \
--mail-rcpt someone@example.com \
--upload-file message.txt \
-u "me@example.com:PASSWORD"

message.txt — это собственно письмо, которое должно соответствовать определённому формату, примеры смотрите на этой странице.

Заключение

Мы подошли к концу, и я уверен, что это было не менее 10 примеров (перестал считать). Но, честно говоря, это лишь малая часть — ведь мы даже не коснулись libcurl, являющейся основной частью curl.

С помощью curl можно сделать гораздо больше, поэтому рекомендую изучить как документацию, так и https://everything.curl.dev/.

Дополнительные материалы

Предыдущая Статья

Зачем нужен элемент dialog

Следующая Статья

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