summaryrefslogtreecommitdiff
path: root/docs/reference/client-basic.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/reference/client-basic.md')
-rw-r--r--docs/reference/client-basic.md183
1 files changed, 183 insertions, 0 deletions
diff --git a/docs/reference/client-basic.md b/docs/reference/client-basic.md
new file mode 100644
index 00000000..a1909f27
--- /dev/null
+++ b/docs/reference/client-basic.md
@@ -0,0 +1,183 @@
+Title: Creating a Basic Client
+Slug: client-basic
+
+# Creating a Basic Client
+
+libsoup provides a feature rich and complete HTTP client feature-set however in this guide we will just be touching the basics.
+
+## Creating a SoupSession
+The core of libsoup is [class@Session]; 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 [ctor@Session.new].
+
+## Downloading Into Memory
+
+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:
+
+```c
+#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;
+}
+```
+
+## Efficiently Streaming Data
+
+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.
+
+```c
+#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;
+}
+```
+
+## Using Asynchronously
+
+If you are using libsoup in an application with a [struct@GLib.MainLoop] 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:
+[method@Session.send_and_read_async] and [method@Session.send_async]. These
+behave the same as all async GLib APIs, for example:
+
+```c
+#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;
+}
+```