Как использовать CURL в Vala

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

Я столкнулся с этой нехваткой информации во время работы над приложением Whaler. Приложение вызывает методы Docker Engine API для управления контейнерами Docker под капотом.

В начале работы над проектом я столкнулся с вопросом: Какую библиотеку использовать для выполнения HTTP-запросов? Существовало важное требование — библиотека должна была поддерживать сокеты UNIX.

Было три варианта:

  • GLib.Socket
  • libsoup-2.4
  • libcurl

GLib.Socket требовал реализации обертки для работы с протоколом HTTP. Libsoup-2.4 не поддерживал сокеты UNIX (они стали доступны начиная с версии 3.0). Поэтому я пропустил первые два варианта и выбрал libcurl. Она имела привязку к Vala и поддерживала сокеты UNIX.

Как добавить libcurl в проект

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

Давайте посмотрим на небольшой демонстрационный проект.

Структура папок:

project/
    meson.build
    app.vala
    vapi/
        libcurl.vapi
        libcurl.deps
Вход в полноэкранный режим Выход из полноэкранного режима

Вы можете скачать libcurl.vapi и libcurl.deps на сайте List of Vala Bindings.

meson.build:

project('com.github.sdv43.vala-recipes.curl', 'vala', 'c', version: '1.0.0')

vapi_dir = meson.current_source_dir() / 'vapi'
add_project_arguments(['--vapidir', vapi_dir], language: 'vala')

executable(
    meson.project_name(),
    'app.vala',
    dependencies: [
        dependency('glib-2.0'),
        meson.get_compiler('vala').find_library('posix'),
        meson.get_compiler('vala').find_library('libcurl', dirs: vapi_dir),
        meson.get_compiler('c').find_library('libcurl'),
    ],
)
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем использовать CURL в app.vala:

void main() {
    var curl = new Curl.EasyHandle();

    // set curl options

    var code = curl.perform();
    assert_true(code == Curl.Code.OK);
}
Войти в полноэкранный режим Выход из полноэкранного режима

Простой интерфейс против многофункционального интерфейса

CURL предоставляет два различных интерфейса: Easy и Multi. Первый работает синхронно, а второй, если я правильно понял, может делать несколько запросов одновременно и работает асинхронно.

Я решил использовать интерфейс Easy, потому что нашел пример, написанный на языке Vala.

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

Я решил выбрать первое решение, которое пришло мне в голову. Это вызов curl_perform в отдельном потоке с помощью GLib.Task. Это предотвращает блокировку основного потока и позволяет приложению работать корректно. Вот пример:

app.vala:

void main() {
    var curl = new Curl.EasyHandle();

    // set curl options

    var task = new Task (null, null, (source_obj, cl_task) => {
        var curl_code = (Curl.Code)cl_task.propagate_int ();
        assert_true(curl_code == Curl.Code.OK);
    });

    task.set_task_data (curl, null);

    task.run_in_thread ((cl_task, source_obj, curl, cancellable) => {
        unowned var cl_curl = (Curl.EasyHandle)curl;

        var code = cl_curl.perform ();
        cl_task.return_int (code);
    });
}
Войти в полноэкранный режим Выход из полноэкранного режима

Окончательное решение, использованное в Whaler, доступно на Github: HttpClient.vala

Ссылки

  • Пример Curl от Richard-W
  • Список привязок Vala
  • Руководство по CURL

Вопросы и что дальше

Я считаю, что это всего лишь один из многих возможных способов выполнения HTTP запросов в Vala. Поэтому я был бы рад услышать ваши мысли:

  • Существуют ли другие HTTP-библиотеки для Vala?
  • Можно ли создать решение без использования GLib.Task? Может ли интерфейс Multi помочь в этом?

Оцените статью
Procodings.ru
Добавить комментарий