1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 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;
}
```
|