curl — учимся тестировать API

Осваиваем быстрый, маленький и простой инструмент тестирования API

“Когда я начал изучать HTTP-протокол и надо было работать с URL-ами и передаваемыми в них данными, в каждом найденном инструменте не хватало хорошей документации, или она была, но в виде избыточно сложных инструкций для простых вещей, типа отправки простого HTTP-запроса. Однажды обратил внимание на curl, которым раньше скачивал файлы, и это оказался лучший инструмент для изучения веб-API.

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

Итак, поехали.

Настройка

Как всякий серьезный софт, curl требует установки в операционной системе. Хорошая новость: скорее всего, он уже установлен! Точнее, встроен в операционку. Уважающий себя тестировщик, разумеется, работает в Linux, а почти каждый дистрибутив Linux уже идет с curl. Более того, даже Windows 10 (начиная с версии 1803) поставляется с curl.

Проверим, есть ли в системе curl.

В Linux набираем в терминале:

curl --version

Если все-таки работаешь в Windows, то запускаешь cmd или, лучше, PowerShell:

curl.exe --version

Команда покажет версию curl, прикрепленные библиотеки, дату релиза, поддерживаемые протоколы и поддерживаемые функции. В Linux увидим следующее:

curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

Если введенная команда выдала ошибку, то curl не установлен, значит его надо скачать и поставить. Еще одна хорошая новость: он бесплатный (но есть нюансы, о которых в конце). Есть версии для практически всех операционных систем, размер ехе-шника не превышает 5 Мб.

Если понадобилось ознакомиться с curl, а опыта с API нет, ситуацию облегчит тестовый httpbin-сервис, примеры с которым приведены далее в этом посте.

Примечание. С этого момента, будут приводиться исключительно «линуксовые» bash-команды, для ясности и читабельности. Если ты сидишь в Windows и примеры почему-то не работают, попробуй добавлять «.exe» после команды curl, или удалять (возможные) лишние пробелы в строках (line breaks).

Базовые опции

Несмотря на то, что Curl очень простой инструмент, он имеет множество различных функций. Начнем с ними знакомиться:

  • --request или -X: Указывает нужный http-метод (здесь подробнее — желательно хорошо разобраться). Если опции нет, запрос по умолчанию обрабатывается как GET. Например: curl -X POST ...
  • --header или -H: В HTTP-запрос добавляется дополнительный заголовок, их может быть сколько угодно. Например: curl -H "X-First-Name: John" -H "X-Last-Name: Doe" ...
  • --data или -d: В запрос включаются какие-то данные. Они могут добавляться в той же строке, или указывать на текстовый файл, откуда считываются. Пример: curl -d "тут текстовые данные" ...
  • -form или -F: curl эмулирует заполненную форму, с нажатием кнопки отправки. Допускается отправка бинарных файлов. Пример: curl -F name=John -F shoesize=11 ...
  • --user <user:password> или -u <user:password>: Логин и пароль для аутентификации на сервере.

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

  • --dump-header или -D: Сохраняет в указанный дамп-файл полученные заголовки. Пример:  curl -D result.header ...
  • --output или -O: Выводит в указанный дамп-файл, минуя stdout. Пример: curl -o result.json ...

GET-метод

Мы познакомились с основами, пора перейти к более серьезным вещам. 

Во первых, меняем текущую папку в командной оболочке, на домашнюю папку или на рабочий стол (desktop), чтобы легче было найти выведенные из curl файлы. 

Делаем первые запросы:

curl -X GET "https://httpbin.org/get" \
-H "accept: application/json" \
-D result.headers \
-o result.json

В первой строке указываем curl выполнить HTTP-запрос GET-методом, по такому-то URL. Во второй строке добавляем заголовок, чтобы сервер знал, что нам отправить в ответе. В третьей строке прописываем вывод полученных заголовков в файл дампа, который мы назовем result.headers. В последней строчке даем указание вывести результат запроса в файл result.json.

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

файл result.headers

HTTP/2 200 
date: Thu, 02 Sep 2021 05:47:14 GMT
content-type: application/json
content-length: 169

В файле result.headers видим, что запрос успешно выполнен, с кодом ответа 200 (все ОК), от сервера получен таймкод ответа (timestamp), и все заголовки.

Файл result.json

{
  "args": {}, 
  "headers": {
    "Accept": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.68.0"
  },
  "url": "https://httpbin.org/get"
}

В этом файле result.json находится тело ответа. Это данные, возвращенные сервером, в красивом JSON-формате (об особенностях формата читаем здесь).

POST-метод

Отправка простого текста

Сейчас попробуем отправить обычный текст (plaintext) на сервер, с помощью метода POST.

curl -X POST "https://httpbin.org/post" \
-H "accept: application/json" \
-H "Content-Type: text/plain" \
-H "Custom-Header: Testing" \
-d "I love hashnode" \
-D result.headers \
-o result.json

Как видим, в запрос включен кастомный заголовок "Custom-Header: Testing". Он должен отображаться в теле ответа.

Смотрим теперь в файл result.headers

HTTP/2 200 
date: Fri, 03 Sep 2021 03:16:20 GMT
content-type: application/json
content-length: 182

и файл result.json

{
  "data": "I love hashnode", 
  "headers": {
    "Accept": "application/json", 
    "Content-Length": "15", 
    "Content-Type": "text/plain", 
    "Custom-Header": "Testing"
  }
}

Видим, что сервер получил plaintext-сообщение с тестовым заголовком и вернул его обратно  без изменений.

Параметры строки запроса

В curl поддерживается не только простой текст, но и достаточно сложные параметры типа:

curl -X POST "https://httpbin.org/post?name=Carlos&last=Jasso" \
-H "accept: application/json" \
-D result.headers \
-o result.json

файл result.headers

HTTP/2 200 
date: Fri, 03 Sep 2021 03:30:47 GMT
content-type: application/json
content-length: 120

файл result.json

{
  "args": {
    "lastname": "Jasso", 
    "name": "Carlos"
  }, 
  "headers": {
    "Accept": "application/json"
  }
}

Сервер, как и предыдущем примере, правильно «зеркалит» параметры, которые curl отправил.

Отправка JSON-объекта

Поставим curl-у задачу посложнее, попытаемся отправить на сервер json-файл и посмотрим что получится:

curl -X POST "https://httpbin.org/post" \
-H "Content-Type: application/json; charset=utf-8" \
-d @data.json \
-o result.json

Тут мы добавили специальный заголовок Content-Type, сообщающий серверу, что ему посылается json-файл. Путь к файлу с данными указывается флагом -d с собачкой @, и далее путь к файлу (в нашем случае это будет текущая папка).

Вот содержимое файла data.json, который надо создать:

{
    "name": "Jane",
    "last": "Doe"
}

И файл result.json:

{
  "data": "{    \"name\": \"Jane\",    \"last\": \"Doe\"}", 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "38", 
    "Content-Type": "application/json; charset=utf-8"
  }, 
  "json": {
    "last": "Doe", 
    "name": "Jane"
  }
}

И снова видим, как curl умеет корректно отправлять контент JSON-файлов на сервер.

Эмуляция отправки значений формы

Иногда может понадобиться имитировать отправку формы. Curl умеет и это:

curl -X POST "https://httpbin.org/post" \
-H "Content-Type: multipart/form-data" \
-F "FavoriteFood=Pizza" \
-F "FavoriteBeverage=Beer" \
-o result.json

Чтобы обозначить для сервера, что посылаются данные формы, добавляется заголовок с соответствующим MIME-типом (как показано выше), плюс параметр -F в каждом из полей и значений.

result.json:

{ 
  "form": {
    "FavoriteBeverage": "Beer", 
    "FavoriteFood": "Pizza"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "261", 
    "Content-Type": "multipart/form-data;"
  }
}

Видим, что сервер получил форму и правильно обработал все поля.

Отправка файла

Выше мы демонстрировали достаточно простые действия. А как насчет передачи файла? Файлы передаются таким же образом, как формы выше. Отправим изображение из текущей папки:

curl -X POST "https://httpbin.org/post" \
-H "Content-Type: multipart/form-data" \
-F "FileComment=This is a JPG file" \
-F "image=@image.jpg" \
-o result.json

result.json:

{
  "files": {
    "image": "data:image/jpeg;base64,/9j/4AAQSkZJ..."
  }, 
  "form": {
    "FileComment": "This is a JPG file"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "78592", 
    "Content-Type": "multipart/form-data;"
  }
}

curl может потребоваться некоторое время чтобы отправить большой файл, а потом сервер вернет этот файл (причем закодированный в Base64). Curl должен правильно обработать такой запрос.

Другие методы

Можно попробовать «погонять» любые запросы, чтобы убедиться, как полезен бывает curl при тестировании API. В целом, обработка запросов зависит от типа API и имплементации метода.

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

curl умеет проводить аутентификацию на сервере, когда по URL-адресу нужен ввод пользовательских имени-пароля. В этом случае httpbin получает ожидаемые имя и пароль в формате /basic-auth/{user}/{passwd} и сопоставляет значения с введенными. Если эти данные не введены, получается следующее:

curl -X GET "https://httpbin.org/basic-auth/carlos/secret" \
-H "accept: application/json" \
-D result.headers

result.headers:

HTTP/2 401 
date: Fri, 03 Sep 2021 04:08:44 GMT
content-length: 0

То есть код 401 (не прошла авторизация).

Добавим в запрос логин и пароль:

curl -X GET "https://httpbin.org/basic-auth/carlos/secret" \
-u carlos:secret
-H "accept: application/json" \
-D result.headers

result.headers:

HTTP/2 200 
date: Fri, 03 Sep 2021 04:14:19 GMT
content-type: application/json
content-length: 48

result.json:

{
  "authenticated": true, 
  "user": "carlos"
}

Все хорошо, авторизация прошла успешно.

Curl позволяет авторизоваться и другими методами — например, с помощью токена. Токен просто отправляется в соответствующем заголовке.

Платный тариф

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

Распространенные инструменты тестирования API — бесплатные, но в них чаще всего бывают платными функции командной работы. Или например, запросы к социальным сетям (Вконтакте и Facebook) блокированы в бесплатном тарифе, и это один из немногих минусов в столь приятном продукте. 

В других похожих инструментах бывает слишком сложный интерфейс, но это не об curl. Для простоты, рекомендую работать в VSCode. Связка VSCode c curl — идеальная.

curl vs code

На скрине слева отрендеренный markdown-документ, справа полученные result.headers и result.json, и терминал внизу, куда тестировщику приходится глядеть чаще всего.

Вопреки убеждению, бытующему в определенных кругах, curl хорошо работает не только в REST-архитектуре, но и в SOAP.

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

Какой была ваша первая зарплата в QA и как вы искали первую работу?

Мега обсуждение в нашем телеграм-канале о поиске первой работы. Обмен опытом и мнения.

4 КОММЕНТАРИИ

Подписаться
Уведомить о
guest

4 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
john snow
john snow
2 лет назад

Уважающий себя тестировщик работает в Linux обязательно? Да сейчас все работают в том, что выдадут на работе. И в 90 процентах случаев это или ноут с windows или макбук.

А так спасибо за материал — curl полезная штука — мы часто используем для идентификации запросов.

Макс
Макс
2 лет назад

Автор у тебя опечатка, в самом начале статьи.
Нужно поменять местами команду для Linux и windows.

Anton Gorchakov
Anton Gorchakov
2 лет назад

Все мои знания cURL ограничиваются заходом в нетворк табу инструментов разработчика, кликом по запросу и выбором «copy as cURL»)

Мы в Telegram

Наш официальный канал
Полезные материалы и тесты
Готовимся к собеседованию
Project- и Product-менеджмент

? Популярное

? Telegram-обсуждения

Наши подписчики обсуждают, как искали первую работу в QA. Некоторые ищут ее прямо сейчас.
Наши подписчики рассказывают о том, как не бояться задавать тупые вопросы и чувствовать себя уверенно в новой команде.
Обсуждаем, куда лучше податься - в менеджмент или по технической ветке?
Говорим о конфликтных ситуациях в команде и о том, как их избежать
$1100*
медианная зарплата в QA в июне 2023

*по результатам опроса QA-инженеров в нашем телеграм-канале

Собеседование

19%*
IT-специалистов переехало или приняло решение о переезде из России по состоянию на конец марта 2022

*по результатам опроса в нашем телеграм-канале

live

Обсуждают сейчас