<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://docbook.org/xml/5.1/rng/docbook.rng" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://docbook.org/xml/5.1/sch/docbook.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<sect1 xmlns="http://docbook.org/ns/docbook" 
    xmlns:xlink="http://www.w3.org/1999/xlink" version="5.1">
    <title>Creating a Basic Client</title>
    <para>libsoup provides a feature rich and complete HTTP client feature-set however in this guide
        we will just be touching the basics. See … for a more in-depth example.</para>
        <sect2>
            <title>Creating a SoupSession</title>
            <para>The core of libsoup is <type>SoupSession</type>; It contains all of the state of a
                client including managing connections, queuing messages, handling authentication and
                redirects, and much more. For now lets assume the default set of options and
                features it provides are acceptable for most usage in which case you simply need to
                create one with <link linkend="soup-session-new"><function>soup_session_new()</function></link>.</para>
        </sect2>
        <sect2>
            <title>Downloading Into Memory</title>
            <para>A common use case is that you simply want to request an HTTP resource and store it
                for later use. There are a few methods of doing this but libsoup provides a high
                level API to accomplish this:</para>
<informalexample><programlisting><![CDATA[#include <libsoup/soup.h>

int main (int argc, char **argv)
{
    SoupSession *session = soup_session_new ();
    SoupMessageHeaders *response_headers;
    const char *content_type;
    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png");
    GError *error = NULL;
    GBytes *bytes = soup_session_send_and_read (
        session,
        msg,
        NULL, // Pass a GCancellable here if you want to cancel a download
        &error);

    if (error) {
        g_printerr ("Failed to download: %s\n", error->message);
        g_error_free (error);
        g_object_unref (msg);
        g_object_unref (session);
        return 1;
    }

    response_headers = soup_message_get_response_headers (msg);
    content_type = soup_message_headers_get_content_type (response_headers);

    // content_type = "image/png"
    // bytes contains the raw data that can be used elsewhere
    g_print ("Downloaded %zu bytes of type %s\n",
             g_bytes_get_size (bytes), content_type);

    g_bytes_unref (bytes);
    g_object_unref (msg);
    g_object_unref (session);
    return 0;
}]]>
</programlisting></informalexample>
        </sect2>
        <sect2>
            <title>Efficiently Streaming Data</title>
            <para>While sometimes you want to store an entire download in memory it is often more
                efficient to stream the data in chunks. In this example we will write the output to
                a file.</para>
            <para>
<informalexample><programlisting><![CDATA[#include <libsoup/soup.h>

int main (int argc, char **argv)
{
    SoupSession *session = soup_session_new ();
    SoupMessageHeaders *response_headers;
    const char *content_type;
    goffset content_length;
    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png");
    GError *error = NULL;
    GInputStream *in_stream = soup_session_send (
        session,
        msg,
        NULL,
        &error);

    if (error) {
        g_printerr ("Failed to download: %s\n", error->message);
        g_error_free (error);
        g_object_unref (msg);
        g_object_unref (session);
        return 1;
    }

    GFile *output_file = g_file_new_tmp ("BBB-Bunny-XXXXXX.png");
    GOutputStream *out_stream = g_file_create (output_file,
        G_FILE_CREATE_NONE, NULL, &error);

    if (error) {
        g_printerr ("Failed to create file \"%s\": %s\n",
                    g_file_peek_path (output_file), error->message);
        g_error_free (error);
        g_object_unref (output_file);
        g_object_unref (in_stream);
        g_object_unref (msg);
        g_object_unref (session);
        return 1;
    }

    response_headers = soup_message_get_response_headers (msg);
    content_type = soup_message_headers_get_content_type (response_headers);
    content_length = soup_message_headers_get_content_length (response_headers);

    // content_type = "image/png"
    g_print ("Downloading %zu bytes of type %s to %s\n",
             content_length, content_type,
             g_file_peek_path (output_file));

    g_output_stream_splice (out_stream, in_stream,
        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
        NULL, &error);

    if (error) {
        g_print ("Download failed: %s\n", error->message);
        g_error_free (error);
    } else {
        g_print ("Download completed\n");
    }

    g_object_unref (output_file);
    g_object_unref (in_stream);
    g_object_unref (out_stream);
    g_object_unref (msg);
    g_object_unref (session);
    return error ? 1 : 0;
}]]>
</programlisting></informalexample>
            </para>
        </sect2>
        <sect2>
            <title>Using Asynchronously</title>
            <para>If you are using libsoup in an application with a <link linkend="GMainLoop"><type>GMainLoop</type></link> such as a GTK application
            you do not want to block the mainloop by doing IO. To accomplish this libsoup provides an
            asynchronous version of each of the APIs: <link linkend="soup-session-send-and-read-async"><function>soup_session_send_and_read_async()</function></link>
            and <link linkend="soup-session-send-async"><function>soup_session_send_async()</function></link>. These behave the same as all async GLib
            APIs, for example:</para>
<informalexample><programlisting><![CDATA[#include <libsoup/soup.h>

static void on_load_callback (GObject *source, GAsyncResult *result, gpointer user_data)
{
    GMainLoop *loop = user_data;
    GError *error = NULL;
    GBytes *bytes = soup_session_send_and_read_finish (SOUP_SESSION (source), result, &error);

    // Usage here is the same as before
    if (error) {
        g_error_free (error);
    } else {
        g_bytes_unref (bytes);
    }

    g_main_loop_quit (loop);
}

int main (int argc, char **argv)
{
    SoupSession *session = soup_session_new ();
    GMainLoop *loop = g_main_loop_new (NULL, FALSE);
    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png");

    soup_session_send_and_read_async (
        session,
        msg,
        G_PRIORITY_DEFAULT,
        NULL,
        on_load_callback,
        loop);

    g_main_loop_run (loop);

    g_main_loop_unref (loop);
    g_object_unref (msg);
    g_object_unref (session);
    return 0;
}]]>
</programlisting></informalexample>
        </sect2>
</sect1>
