[libsoup] docs: More progress on improving tutorial
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] docs: More progress on improving tutorial
- Date: Tue, 8 Dec 2020 21:13:12 +0000 (UTC)
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 <libsoup/soup.h>
</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]