<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Selivestrov Dmitriy</title>
    <description>The latest articles on DEV Community by Selivestrov Dmitriy (@sdv43).</description>
    <link>https://dev.to/sdv43</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F641295%2Fad2347ed-124f-4bf4-b65c-8d46116d442b.png</url>
      <title>DEV Community: Selivestrov Dmitriy</title>
      <link>https://dev.to/sdv43</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sdv43"/>
    <language>en</language>
    <item>
      <title>How to use CURL in Vala</title>
      <dc:creator>Selivestrov Dmitriy</dc:creator>
      <pubDate>Thu, 05 May 2022 17:04:14 +0000</pubDate>
      <link>https://dev.to/sdv43/how-to-use-curl-in-vala-i60</link>
      <guid>https://dev.to/sdv43/how-to-use-curl-in-vala-i60</guid>
      <description>&lt;p&gt;Hi everyone! Nowadays there are a lot of applications written in Vala that make HTTP requests and various libraries that can help with it. At the same time, there is a certain lack of information on how to make requests via curl. This article is aimed to cover the gap.&lt;/p&gt;

&lt;p&gt;I've encountered this lack of info while working on the &lt;a href="https://github.com/sdv43/whaler"&gt;Whaler&lt;/a&gt; app. The app calls Docker Engine API methods to manage Docker containers under the hood. &lt;/p&gt;

&lt;p&gt;At the start of the project, I faced a question: Which library should I use to make HTTP requests? There was an important requirement - the library had to support UNIX sockets.&lt;/p&gt;

&lt;p&gt;There were three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GLib.Socket&lt;/li&gt;
&lt;li&gt;libsoup-2.4&lt;/li&gt;
&lt;li&gt;libcurl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GLib.Socket required implementing a wrapper to work with the HTTP protocol. Libsoup-2.4 didn't support UNIX sockets (they became available starting from the 3.0 version). That’s why I skipped the first two and chose libcurl. It had Vala bindings and supported UNIX sockets.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add libcurl to a project
&lt;/h2&gt;

&lt;p&gt;First of all, check if libcurl is installed on your system. If not, make sure to install it.&lt;/p&gt;

&lt;p&gt;Let’s have a look at a small demo project. &lt;/p&gt;

&lt;p&gt;Folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
    meson.build
    app.vala
    vapi/
        libcurl.vapi
        libcurl.deps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can download libcurl.vapi and libcurl.deps on &lt;a href="https://wiki.gnome.org/Projects/Vala/ListOfBindings#A.22vala-extra-vapis.22_Git_Repository"&gt;List of Vala Bindings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;meson.build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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'),
    ],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use CURL in the app.vala:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vala"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EasyHandle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// set curl options&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;assert_true&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Easy interface vs. Multi interface
&lt;/h2&gt;

&lt;p&gt;CURL provides two different interfaces: Easy and Multi. The first one works synchronously and the second one, if I got it right, can make several requests simultaneously and works in asynchronous manner.&lt;/p&gt;

&lt;p&gt;I chose to use the Easy interface because I found an &lt;a href="https://github.com/Richard-W/curl-vala"&gt;example&lt;/a&gt; written in Vala. &lt;/p&gt;

&lt;p&gt;The last problem to be solved was the one with blocking the thread when calling &lt;code&gt;curl_perform&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I decided to go with the first solution that came to mind. That is to call &lt;code&gt;curl_perform&lt;/code&gt; in a separate thread by using GLib.Task. It prevents the main thread from blocking and allows the app to work correctly. Here is an example:&lt;/p&gt;

&lt;p&gt;app.vala:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vala"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EasyHandle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// set curl options&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cl_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;curl_code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;cl_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;propagate_int&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;assert_true&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curl_code&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_task_data&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_in_thread&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cl_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;unowned&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cl_curl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EasyHandle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cl_curl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;cl_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;return_int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final solution used in Whaler is available on Github: &lt;a href="https://github.com/sdv43/whaler/blob/master/src/Utils/HttpClient.vala"&gt;HttpClient.vala&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Curl example from &lt;a href="https://github.com/Richard-W/curl-vala"&gt;Richard-W&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.gnome.org/Projects/Vala/ListOfBindings#A.22vala-extra-vapis.22_Git_Repository"&gt;List of Vala Bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://curl.se/libcurl/c/"&gt;CURL Manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Questions &amp;amp; What's next
&lt;/h2&gt;

&lt;p&gt;I believe it is just one of many possible ways to make HTTP requests in Vala. So I would be happy to hear your thoughts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are there any other HTTP libraries for Vala?&lt;/li&gt;
&lt;li&gt;Is it possible to create a solution without using GLib.Task? Can the Multi interface help with it?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gtk</category>
      <category>vala</category>
      <category>curl</category>
      <category>glib</category>
    </item>
  </channel>
</rss>
