[libsoup] docs: More progress on improving tutorial



commit 48e48a1b4f09d6a8f3a237933be833613b01e5d2
Author: Patrick Griffis <pgriffis igalia com>
Date:   Tue Dec 8 15:12:59 2020 -0600

    docs: More progress on improving tutorial

 docs/reference/build-howto.xml              | 150 ++++++++------------
 docs/reference/client-advanced.xml          | 203 ++++++++++++++++++++++++++++
 docs/reference/client-basic.xml             | 171 +++++++++++++++++++++++
 docs/reference/client-tls.xml               | 134 ++++++++++++++++++
 docs/reference/libsoup-3.0-docs.xml         |   6 +-
 docs/reference/meson.build                  |   4 +-
 docs/reference/migrating-from-libsoup-2.xml |   2 +-
 7 files changed, 573 insertions(+), 97 deletions(-)
---
diff --git a/docs/reference/build-howto.xml b/docs/reference/build-howto.xml
index 1eb34ac6..de4e831f 100644
--- a/docs/reference/build-howto.xml
+++ b/docs/reference/build-howto.xml
@@ -1,45 +1,26 @@
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
-               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd";>
-<refentry id="libsoup-build-howto">
-<refmeta>
-<refentrytitle>Compiling with libsoup</refentrytitle>
-<manvolnum>3</manvolnum>
-<refmiscinfo>LIBSOUP Library</refmiscinfo>
-</refmeta>
-
-<refnamediv>
-<refname>Compiling with libsoup</refname><refpurpose>Notes on compiling</refpurpose>
-</refnamediv>
-
-<refsect2>
-<title>Using pkg-config</title>
-
-<para>
-Like other GNOME libraries, <application>libsoup</application> uses
-<application>pkg-config</application> to provide compiler options. The
-package name is "<literal>libsoup-3.0</literal>". So in your
-<literal>configure</literal> script, you might specify something like:
-</para>
-
-<informalexample><programlisting>
-PKG_CHECK_MODULES(LIBSOUP, [libsoup-3.0 >= 2.26])
+<?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>Building with libsoup</title>
+    <sect3>
+      <title>Buildsystem Integration</title>
+    <para>Like other GNOME libraries, <application>libsoup</application> uses
+            <application>pkg-config</application> to provide compiler options. The package name is
+            "<literal>libsoup-3.0</literal>". </para>
+    <para>For example if you use Autotools:<informalexample>
+    <programlisting>PKG_CHECK_MODULES(LIBSOUP, [libsoup-3.0])
 AC_SUBST(LIBSOUP_CFLAGS)
-AC_SUBST(LIBSOUP_LIBS)
-</programlisting></informalexample>
-
-<para>
-The "<literal>3.0</literal>" in the package name is the "API version"
-(indicating "the version of the <application>libsoup</application> API
-that first appeared in version 3.0") and is essentially just part of
-the package name.
-</para>
-
-</refsect2>
-
-<refsect2>
-<title>API Availability and Deprecation Warnings</title>
-
+AC_SUBST(LIBSOUP_LIBS)</programlisting>
+        </informalexample></para>
+    <para>If you use Meson: <informalexample>
+            <programlisting>libsoup_dep = dependency('libsoup-3.0')</programlisting>
+        </informalexample></para>
+    </sect3>
+
+    <sect3>
+      <title>API Availability and Deprecation Warnings</title>
 <para>
 If you want to restrict your program to a particular
 <application>libsoup</application> version or range of versions, you
@@ -47,60 +28,43 @@ can define <link
 linkend="SOUP-VERSION-MIN-REQUIRED:CAPS"><literal>SOUP_VERSION_MIN_REQUIRED</literal></link>
 and/or <link
 linkend="SOUP-VERSION-MAX-ALLOWED:CAPS"><literal>SOUP_VERSION_MAX_ALLOWED</literal></link>.
-Eg:
-</para>
-
-<informalexample><programlisting>
-LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_36"
-LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_40"
-</programlisting></informalexample>
-
-<para>
-The <literal>SOUP_VERSION_MIN_REQUIRED</literal> declaration states
-that the code is not expected to compile on versions of
-<application>libsoup</application> older than the indicated version
-(here, 2.36), and so the compiler should print warnings if the code
-uses functions that were deprecated as of that release.
-</para>
-
-<para>
-The <literal>SOUP_VERSION_MAX_ALLOWED</literal> declaration states
-that the code <emphasis>is</emphasis> expected to compile on versions
-of <application>libsoup</application> up to the indicated version
-(here, 2.40), and so, when compiling the program against a newer
-version than that, the compiler should print warnings if the code uses
-functions that did not yet exist in the max-allowed release.
-</para>
-
-<para>
-You can use <link
-linkend="SOUP-CHECK-VERSION:CAPS"><literal>SOUP_CHECK_VERSION</literal></link>
-to check the version of libsoup at compile time, to compile different
-code for different <application>libsoup</application> versions. (If
-you are setting <literal>SOUP_VERSION_MIN_REQUIRED</literal> and
-<literal>SOUP_VERSION_MAX_ALLOWED</literal> to different versions, as
-in the example above, then you almost certainly need to be doing
-this.)
-</para>
-
-</refsect2>
-
-<refsect2>
-<title>Headers</title>
-
-<para>
-Code using <application>libsoup</application> should do:
+For example with Autotools:
 </para>
 
+<informalexample><programlisting>LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS 
-DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_3_0"
+LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS 
-DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_2"</programlisting></informalexample>
+
+  <para>Or with Meson:</para>
+
+  <informalexample><programlisting>add_project_arguments(
+  '-DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_3_0',
+  '-DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_2',
+  language: 'c'
+)</programlisting></informalexample>
+  
+<para>The <literal>SOUP_VERSION_MIN_REQUIRED</literal> declaration states that the code is not
+        expected to compile on versions of <application>libsoup</application> older than the
+        indicated version (here, 3.0), and so the compiler should print warnings if the code uses
+        functions that were deprecated as of that release.</para>
+
+<para>The <literal>SOUP_VERSION_MAX_ALLOWED</literal> declaration states that the code
+            <emphasis>is</emphasis> expected to compile on versions of
+            <application>libsoup</application> up to the indicated version (here, 3.2), and so, when
+        compiling the program against a newer version than that, the compiler should print warnings
+        if the code uses functions that did not yet exist in the max-allowed release.</para>
+
+<para>You can use <link linkend="SOUP-CHECK-VERSION:CAPS"><literal>SOUP_CHECK_VERSION</literal></link> to 
check the version of libsoup at compile
+        time, to compile different code for different <application>libsoup</application> versions.
+        (If you are setting <literal>SOUP_VERSION_MIN_REQUIRED</literal> and
+            <literal>SOUP_VERSION_MAX_ALLOWED</literal> to different versions, as in the example
+        above, then you almost certainly need to be doing this.)</para>
+  </sect3>
+  <sect3>
+    <title>Headers</title>
+
+    <para>Code using <application>libsoup</application> should include the header like so:</para>
 <informalexample><programlisting>
 #include &lt;libsoup/soup.h&gt;
 </programlisting></informalexample>
-
-<para>
-Including individual headers rather than <literal>soup.h</literal> is not
-recommended.
-</para>
-
-</refsect2>
-
-</refentry>
+  </sect3>
+</sect1>
diff --git a/docs/reference/client-advanced.xml b/docs/reference/client-advanced.xml
new file mode 100644
index 00000000..f7057c07
--- /dev/null
+++ b/docs/reference/client-advanced.xml
@@ -0,0 +1,203 @@
+<?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>Advanced Usage</title>
+  <sect2>
+    <title>Customizing Session Options</title>
+    <para>When you create the session with <link 
linkend="soup-session-new-with-options"><function>soup_session_new_with_options()</function></link>,
+    you can specify various additional options. See the <link
+linkend="SoupSession"><type>SoupSession</type> documentation</link> for more details but these may be 
interesting:
+    <link linkend="SoupSession:max-conns"><literal>SoupSession:max-conns</literal></link> and <link 
linkend="SoupSession:max-conns-per-host"><literal>SoupSession:max-conns-per-host</literal></link>,
+    <link linkend="SoupSession:user-agent"><literal>SoupSession:user-agent</literal></link>, <link 
linkend="SoupSession:timeout"><literal>SoupSession:timeout</literal></link>,
+    <link linkend="SoupSession:accept-language"><literal>SoupSession:accept-language</literal></link> and 
<link 
linkend="SoupSession:accept-language-auto"><literal>SoupSession:accept-language-auto</literal></link></para>
+  </sect2>
+  <sect2>
+    <title>Adding Session Features</title>
+       <para>Additional session functionality is provided as <link
+linkend="SoupSessionFeature"><type>SoupSessionFeature</type></link>s,
+which can be added to or removed from a session.</para>
+
+       <para>One such feature is <link linkend="SoupContentDecoder"><type>SoupContentDecoder</type></link>
+    which is added by default. This advertises to servers that the
+client supports compression, and automatically decompresses compressed
+responses.
+</para>
+<para>
+Some other available features that you can add include:
+</para>
+
+<variablelist>
+    <varlistentry>
+       <term><link linkend="SoupLogger"><type>SoupLogger</type></link></term>
+       <listitem><para>
+           A debugging aid, which logs all of libsoup's HTTP traffic
+           to <literal>stdout</literal> (or another place you specify).
+       </para></listitem>
+    </varlistentry>
+    <varlistentry>
+       <term>
+           <link linkend="SoupCookieJar"><type>SoupCookieJar</type></link>,
+           <link linkend="SoupCookieJarText"><type>SoupCookieJarText</type></link>,
+           and <link linkend="SoupCookieJarDB"><type>SoupCookieJarDB</type></link>
+       </term>
+       <listitem><para>
+           Support for HTTP cookies. <type>SoupCookieJar</type>
+           provides non-persistent cookie storage, while
+           <type>SoupCookieJarText</type> uses a text file to keep
+           track of cookies between sessions, and
+           <type>SoupCookieJarDB</type> uses a
+           <application>SQLite</application> database.
+       </para></listitem>
+    </varlistentry>
+    <varlistentry>
+       <term><link linkend="SoupContentSniffer"><type>SoupContentSniffer</type></link></term>
+       <listitem><para>
+           Uses the HTML5 sniffing rules to attempt to
+           determine the Content-Type of a response when the
+           server does not identify the Content-Type, or appears to
+           have provided an incorrect one. 
+       </para></listitem>
+    </varlistentry>
+</variablelist>
+
+<para>
+Use the <link
+linkend="soup-session-add-feature-by-type"><function>soup_session_add_feature_by_type()</function></link> 
function to
+add features that don't require any configuration (such as <link
+linkend="SoupContentSniffer"><type>SoupContentSniffer</type></link>),
+and the <link
+linkend="soup-session-add-feature"><function>soup_session_add_feature()</function></link>function to add 
features that must be
+constructed first (such as <link
+linkend="SoupLogger"><type>SoupLogger</type></link>). For example, an
+application might do something like the following:
+</para>
+
+<informalexample><programlisting><![CDATA[session = soup_session_new ();
+soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
+
+if (debug_level) {
+    SoupLogger *logger = soup_logger_new (debug_level);
+    soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
+    g_object_unref (logger);
+}]]></programlisting></informalexample>
+
+    <para>You can also remove features by calling <link
+linkend="soup-session-remove-feature"><function>soup_session_remove_feature()</function></link> or
+<link
+linkend="soup-session-remove-feature-by-type"><function>soup_session_remove_feature_by_type()</function></link></para>.
+
+    <para>See the <link linkend="additional-features">Additional Features</link> section for other features.
+    </para>
+  </sect2>
+  <sect2>
+    <title>Using a proxy</title>
+    <para>By default libsoup tries to respect the default proxy (as best as <link
+linkend="g-proxy-resolver-get-default"><function>g_proxy_resolver_get_default()</function></link> knows), 
however you can set
+    a custom one or disable it outright using the <link 
linkend="SoupSession:proxy-resolver"><literal>SoupSession:proxy-resolver</literal></link>
+    property. For example:</para>
+<informalexample><programlisting><![CDATA[
+{
+    GProxyResolver *resolver = g_simple_proxy_resolver_new ("https://my-proxy-example.org";, NULL);
+    SoupSession *session = soup_session_new_with_options ("proxy-resolver", resolver, NULL);
+    g_object_unref (resolver);
+}]]>
+</programlisting></informalexample>
+  </sect2>
+  <sect2>
+    <title>Using the SoupMessage API</title>
+    <para>The <type>SoupMessage</type> type contains all the state for a request and response pair that you 
send and recieve
+    to a server. For many more complex tasks you will have to create one of these and send it with the 
<function>soup_session_send()</function>
+    function. For example this sends a request with the <literal>HEAD</literal> method:
+    </para>
+<informalexample><programlisting><![CDATA[
+{
+    SoupSession *session = soup_session_new ();
+    SoupMessage *msg = soup_message_new (SOUP_METHOD_HEAD, "https://example.org";);
+
+    // This allows you to also customize the request headers:
+    SoupMessageHeaders *request_headers = soup_message_get_request_headers (msg);
+    soup_message_headers_replace (request_headers, "Foo", "Bar");
+
+    GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
+    if (in_stream) {
+        g_print ("Message was sent and recived a response of %u (%s)\n",
+                 soup_message_get_status (msg), soup_message_get_reason_phrase (msg));
+        // You can also inspect the response headers via soup_message_get_response_headers();
+        g_object_unref (in_stream);
+    }
+
+    g_object_unref (msg);
+    g_object_unref (session);
+}]]>
+</programlisting></informalexample>
+  </sect2>
+  <sect2>
+    <title>Controlling Redirections</title>
+    <para>By default libsoup automatically handles redirections in a sane way without you needing to worry 
about it.
+    However you may want explicitly block all redirections or perhaps allow some unsafe redirections. 
<literal>SoupMessage::redirection</literal>
+    provides a way to do both of these:</para>
+<informalexample><programlisting><![CDATA[
+static SoupMessageRedirectionFlags
+redirection_callback (SoupMessage *msg, GUri *location, guint redirect_count, gpointer user_data)
+{
+    // Here we could compare URIs, check redirect_count, etc. This just always prevents it.
+    return SOUP_MESSAGE_REDIRECTION_BLOCK;
+}
+
+int main (int argc, char **argv)
+{
+    SoupSession *session = soup_session_new ();
+    // Google redirects to https://www.google.com/
+    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://google.com";);
+    g_signal_connect (msg, "redirection", G_CALLBACK (redirection_callback), NULL);
+    GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
+
+    if (in_stream) {
+        // The redirection was not allowed so we get the status code
+        // soup_message_get_uri() will also show its unchanged
+        g_assert (soup_message_get_status (msg) == SOUP_STATUS_MOVED_PERMANENTLY);
+        g_object_unref (in_stream);
+    }
+
+    return 0;
+}]]>
+</programlisting></informalexample>
+  </sect2>
+  <sect2>
+    <title>Handling authentication</title>
+<informalexample><programlisting><![CDATA[
+static gboolean
+authenticate_callback (SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data)
+{
+    if (retrying) {
+        // Maybe don't try again if our password failed
+        return FALSE;
+    }
+
+    soup_auth_authenticate (auth, "username", "password");
+
+    // Returning TRUE means we have or *will* handle it.
+    // soup_auth_authenticate() or soup_auth_cancel() can be called later
+    // for example after showing a prompt to the user or loading the password
+    // from a keyring.
+    return TRUE;
+}
+
+int main (int argc, char **argv)
+{
+    SoupSession *session = soup_session_new ();
+    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://example.org";);
+    g_signal_connect (msg, "authenticate", G_CALLBACK (authenticate_callback), NULL);
+    GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
+
+    if (in_stream) {
+        g_object_unref (in_stream);
+    }
+
+    return 0;
+}]]>
+</programlisting></informalexample>
+  </sect2>
+</sect1>
\ No newline at end of file
diff --git a/docs/reference/client-basic.xml b/docs/reference/client-basic.xml
new file mode 100644
index 00000000..9477a8db
--- /dev/null
+++ b/docs/reference/client-basic.xml
@@ -0,0 +1,171 @@
+<?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 ();
+    char *content_type;
+    GError *error = NULL;
+    GBytes *bytes = soup_session_load_uri_bytes (
+        session,
+        "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png";,
+        NULL, // Pass a GCancellable here if you want to cancel a download
+        &content_type,
+        &error);
+
+    if (error) {
+        g_printerr ("Failed to download: %s\n", error->message);
+        g_error_free (error);
+        g_object_unref (session);
+        return 1;
+    }
+
+    // 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_free (content_type);
+    g_bytes_unref (bytes);
+    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 ();
+    char *content_type;
+    goffset content_length;
+    GError *error = NULL;
+    GInputStream *in_stream = soup_session_read_uri (
+        session,
+        "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png";,
+        NULL,
+        &content_length,
+        &content_type,
+        &error);
+
+    if (error) {
+        g_printerr ("Failed to download: %s\n", error->message);
+        g_error_free (error);
+        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 (session);
+        return 1;
+    }
+
+    // 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_free (content_type);
+    g_object_unref (output_file);
+    g_object_unref (in_stream);
+    g_object_unref (out_stream);
+    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-load-uri-bytes-async"><function>soup_session_load_uri_bytes_async()</function></link>
+            and <link 
linkend="soup-session-read-uri-async"><function>soup_session_read_uri_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_load_uri_bytes_finish (SOUP_SESSION (source), result,
+                                                        NULL, &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);
+
+    soup_session_load_uri_bytes_async (
+        session,
+        "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png";,
+        G_PRIORITY_DEFAULT,
+        NULL,
+        on_load_callback,
+        loop); 
+
+    g_main_loop_run (loop);
+
+    g_main_loop_unref (loop);
+    g_object_unref (session);
+    return 0;
+}]]>
+</programlisting></informalexample>
+        </sect2>
+</sect1>
\ No newline at end of file
diff --git a/docs/reference/client-tls.xml b/docs/reference/client-tls.xml
new file mode 100644
index 00000000..6f80b112
--- /dev/null
+++ b/docs/reference/client-tls.xml
@@ -0,0 +1,134 @@
+<?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>Everything TLS Related</title>
+  <para>libsoup comes with TLS support provided by glib-networking. This has multiple backends
+  including gnutls (default on all platforms), SChannel on Windows, or OpenSSL.</para>
+  <sect2>
+    <title>Accepting Invalid or Pinned Certificates</title>
+    <para>This makes use of the <literal>SoupMessage::accept-certificate</literal> signal.</para>
+<informalexample><programlisting><![CDATA[
+static gboolean
+accept_certificate_callback (SoupMessage *msg, GTlsCertificate *certificate,
+                             GTlsCertificateFlags tls_errors, gpointer user_data)
+{
+    // Here you can inspect @certificate or compare it against a trusted one
+    // and you can see what is considered invalid by @tls_errors.
+    // Returning TRUE trusts it anyway.
+    return TRUE;
+}
+
+int main (int argc, char **argv)
+{
+    SoupSession *session = soup_session_new ();
+    SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://example.org";);
+    g_signal_connect (msg, "accept-certificate", G_CALLBACK (accept_certificate_callback), NULL);
+    GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
+
+    if (in_stream) {
+        g_object_unref (in_stream);
+    }
+
+    return 0;
+}]]>
+</programlisting></informalexample>
+  </sect2>
+  <sect2>
+    <title>Setting a Custom CA</title>
+<informalexample><programlisting><![CDATA[
+{
+    GError *error = NULL;
+    // NOTE: This is blocking IO
+    GTlsDatabase *tls_db = g_tls_file_database_new ("/foo/ca.pem", &error);
+
+    if (error) {
+        g_printerr ("Failed to load certificates: %s\n", error->message);
+        g_error_free (error);
+        return;
+    }
+
+    SoupSession *session = soup_session_new_with_options ("tls-database", tls_db, NULL);
+    g_object_unref (tls_db);
+}]]>
+</programlisting></informalexample>
+  </sect2>
+  <sect2>
+    <title>Using Client Certificates</title>
+<informalexample><programlisting><![CDATA[
+// We must create a custom GTlsInteraction so lets do that inline
+typedef struct _GetTlsCertInteraction        GetTlsCertInteraction;
+typedef struct _GetTlsCertInteractionClass   GetTlsCertInteractionClass;
+
+static GType                    _get_tls_cert_interaction_get_type    (void) G_GNUC_CONST;
+static GetTlsCertInteraction *  _get_tls_cert_interaction_new         (GTlsCertificate *cert);
+
+struct _GetTlsCertInteraction
+{
+       GTlsInteraction parent_instance;
+       GTlsCertificate *cert;
+};
+
+struct _GetTlsCertInteractionClass
+{
+       GTlsInteractionClass parent_class;
+};
+
+G_DEFINE_TYPE (GetTlsCertInteraction, _get_tls_cert_interaction, G_TYPE_TLS_INTERACTION);
+
+static GTlsInteractionResult
+request_certificate (GTlsInteraction              *interaction,
+                     GTlsConnection               *connection,
+                     GTlsCertificateRequestFlags   flags,
+                     GCancellable                 *cancellable,
+                     GError                      **error)
+{
+       GetTlsCertInteraction *self = (GetTlsCertInteraction*)interaction;
+       g_tls_connection_set_certificate (connection, self->cert);
+       return G_TLS_INTERACTION_HANDLED;
+}
+
+static void
+_get_tls_cert_interaction_init (GetTlsCertInteraction *interaction)
+{
+}
+
+static void
+_get_tls_cert_interaction_class_init (GetTlsCertInteractionClass *klass)
+{
+       GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+       interaction_class->request_certificate = request_certificate;
+}
+
+GetTlsCertInteraction *
+_get_tls_cert_interaction_new (GTlsCertificate *cert)
+{
+       GetTlsCertInteraction *self = g_object_new (_get_tls_cert_interaction_get_type (), NULL);
+       self->cert = g_object_ref (cert);
+       return self;
+}
+
+int main (int argc, char **argv)
+{
+    GError *error = NULL;
+    GTlsCertificate *client_cert = g_tls_certificate_new_from_file ("/foo/cert.pem", &error);
+
+    if (error) {
+        g_printerr ("Failed to load certificate: %s\n", error->message);
+        g_error_free (error);
+        return 1;
+    }
+
+    GTlsInteraction *interaction = _get_tls_cert_interaction_new (cert);
+    SoupSession *session = soup_session_new_with_options ("tls-interaction", interaction, NULL);
+
+    // Send a message
+
+    g_object_unref (interaction);
+    g_object_unref (client_cert);
+    return 0;
+}]]>
+</programlisting></informalexample>
+  </sect2>
+</sect1>
\ No newline at end of file
diff --git a/docs/reference/libsoup-3.0-docs.xml b/docs/reference/libsoup-3.0-docs.xml
index bfa6971c..3130a35b 100644
--- a/docs/reference/libsoup-3.0-docs.xml
+++ b/docs/reference/libsoup-3.0-docs.xml
@@ -15,7 +15,9 @@
     <chapter>
         <title>Tutorial</title>
         <xi:include href="build-howto.xml"/>
-        <xi:include href="client-howto.xml"/>
+        <xi:include href="client-basic.xml"/>
+        <xi:include href="client-advanced.xml"/>
+        <xi:include href="client-tls.xml"/>
         <xi:include href="server-howto.xml"/>
     </chapter>
 
@@ -44,7 +46,7 @@
         <xi:include href="xml/soup-message-body.xml"/>
     </chapter>
 
-    <chapter>
+    <chapter id="additional-features">
         <title>Additional Features</title>
         <xi:include href="xml/soup-session-feature.xml"/>
         <xi:include href="xml/soup-content-decoder.xml"/>
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index b8982daf..de514e29 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -66,7 +66,9 @@ gnome.gtkdoc('libsoup-3.0',
   install : true,
   content_files: [
     'build-howto.xml',
-    'client-howto.xml',
+    'client-basic.xml',
+    'client-advanced.xml',
+    'client-tls.xml',
     'server-howto.xml',
     'migrating-from-libsoup-2.xml',
   ],
diff --git a/docs/reference/migrating-from-libsoup-2.xml b/docs/reference/migrating-from-libsoup-2.xml
index 359a3473..3276489f 100644
--- a/docs/reference/migrating-from-libsoup-2.xml
+++ b/docs/reference/migrating-from-libsoup-2.xml
@@ -49,7 +49,7 @@ linkend="soup-uri-decode-data-uri"><function>soup_uri_decode_data_uri()</functio
                         <link 
linkend="g-proxy-resolver-get-default"><function>g_proxy_resolver_get_default()</function></link></para>
                 </listitem>
                 <listitem>
-                    <para><type>SoupBuffer</type> has been replaced by <link 
linkend="GBytes"><type>GBytes</type></link> and <link 
linkend="GBytesArray"><type>GBytesArray</type></link></para>
+                    <para><type>SoupBuffer</type> has been replaced by <link 
linkend="GBytes"><type>GBytes</type></link> and <link 
linkend="GByteArray"><type>GByteArray</type></link></para>
                 </listitem>
                 <listitem>
                     <para><type>SoupDate</type> has been replaced by <link 
linkend="GDateTime"><type>GDateTime</type></link></para>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]