### Asynchronous Session Send and Read Example Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-basic.md This C code demonstrates how to use `soup_session_send_and_read_async` to perform an asynchronous network request without blocking the `GLib.MainLoop`. It includes a callback function `on_load_callback` that is executed upon completion of the request. ```c #include 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; } ``` -------------------------------- ### Stream Downloaded Data to File with SoupSession Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-basic.md Utilize `soup_session_send` to get an input stream for an HTTP resource, then `g_output_stream_splice` to efficiently transfer data to a file. This method is recommended for larger files to avoid high memory consumption. Remember to handle errors and unreference objects. ```c #include 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; } ``` -------------------------------- ### Get libsoup dependency with Meson Source: https://github.com/gnome/libsoup/blob/master/docs/reference/build-howto.md Declare a dependency on libsoup-3.0 in your Meson build configuration. ```meson libsoup_dep = dependency('libsoup-3.0') ``` -------------------------------- ### Get SoupMessage Method Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_method()` to retrieve the HTTP method of a SoupMessage. This replaces direct struct field access. ```c soup_message_get_method() ``` -------------------------------- ### Get SoupMessage Request Headers Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_request_headers()` to retrieve the request headers of a SoupMessage. This replaces direct struct field access. ```c soup_message_get_request_headers() ``` -------------------------------- ### Get SoupMessage Response Headers Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_response_headers()` to retrieve the response headers of a SoupMessage. This replaces direct struct field access. ```c soup_message_get_response_headers() ``` -------------------------------- ### Get SoupMessage URI Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_uri()` to retrieve the URI associated with a SoupMessage. This replaces direct struct field access. ```c soup_message_get_uri() ``` -------------------------------- ### Get SoupMessage Status Code Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_status()` to retrieve the HTTP status code of a SoupMessage. This replaces direct struct field access. ```c soup_message_get_status() ``` -------------------------------- ### Get SoupMessage Reason Phrase Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_get_reason_phrase()` to retrieve the reason phrase for a SoupMessage's status code. This replaces direct struct field access. ```c soup_message_get_reason_phrase() ``` -------------------------------- ### Set minimum and maximum allowed libsoup versions with Meson Source: https://github.com/gnome/libsoup/blob/master/docs/reference/build-howto.md Use add_project_arguments to set SOUP_VERSION_MIN_REQUIRED and SOUP_VERSION_MAX_ALLOWED for C compilation in Meson. ```meson add_project_arguments( '-DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_99', '-DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_0', language: 'c' ) ``` -------------------------------- ### Implement Custom Authentication Callback in C Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-advanced.md Use this callback to handle authentication challenges from servers. Returning TRUE indicates that authentication will be handled, allowing for credentials to be provided via `soup_auth_authenticate` or cancelled with `soup_auth_cancel`. This is useful for loading credentials from a keyring or prompting the user. ```c 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; } ``` -------------------------------- ### Implement Basic Authentication Callback Source: https://github.com/gnome/libsoup/blob/master/docs/reference/server-howto.md Implement the callback function for basic authentication. This function receives the username and password from the client and must validate them against a server-side user database. It returns TRUE if authentication is successful, FALSE otherwise. Note: Storing cleartext passwords is not recommended. ```c static gboolean auth_callback (SoupAuthDomain *domain, SoupServerMessage *msg, const char *username, const char *password, gpointer user_data) { MyServerData *server_data = user_data; MyUserData *user; user = my_server_data_lookup_user (server_data, username); if (!user) return FALSE; /* FIXME: Don't do this. Keeping a cleartext password database * is bad. */ return strcmp (password, user->password) == 0; ``` -------------------------------- ### Send HEAD Request with SoupMessage API Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-advanced.md Illustrates sending a HEAD request and customizing headers using the `SoupMessage` API. It shows how to create a message, set headers, send it via `soup_session_send`, and inspect the response. ```c { 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); } ``` -------------------------------- ### Configure Proxy Resolver in libsoup Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-advanced.md Shows how to set a custom proxy resolver for a libsoup session using `g_simple_proxy_resolver_new` and `soup_session_new_with_options`. ```c { 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); } ``` -------------------------------- ### Download Resource to Memory with SoupSession Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-basic.md Use `soup_session_send_and_read` to download an HTTP resource and store its content in memory as a GBytes object. This is suitable for smaller resources where the entire content needs to be available at once. Ensure proper error handling and object unreferencing. ```c #include 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; } ``` -------------------------------- ### Use Client Certificates with libsoup Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-tls.md Configure a `SoupMessage` to use a client certificate for authentication. This can be set directly or dynamically requested using the `request-certificate` signal, which is useful for interactive prompts. ```c static gboolean on_request_certificate (SoupMessage *msg, GTlsClientConnection *conn, gpointer user_data) { GTlsCertificate *client_cert = user_data; /* We immediately set this however you can set this later in an async function. */ soup_message_set_tls_client_certificate (msg, client_cert); return TRUE; /* We handled the request */ } 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; } SoupSession *session = soup_session_new (); SoupMessage *msg = soup_message_new ("GET", "https://example.org"); /* We can set the certificate ahead of time if we already have one */ // soup_message_set_tls_client_certificate (msg, client_cert) /* However we can also dynamically request one which is useful in * applications that show a graphical prompt for example. */ g_signal_connect (msg, "request-certificate", G_CALLBACK (on_request_certificate), client_cert); // Send the message... g_object_unref (msg); g_object_unref (session); g_object_unref (client_cert); return 0; } ``` -------------------------------- ### Set Request Body with GIOStream Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Set a request body using a GIOStream. ```c soup_message_set_request_body (msg, "application/json", stream); ``` -------------------------------- ### Compare GLib Uri Equality Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `g_uri_equal()` to check for equality between two GLib.Uri instances, as `GUri` does not provide a direct equality check. ```c g_uri_equal (uri1, uri2) ``` -------------------------------- ### Add Basic Authentication Domain to SoupServer Source: https://github.com/gnome/libsoup/blob/master/docs/reference/server-howto.md Create and add a basic authentication domain to a SoupServer. This involves specifying the realm, callback functions, and paths for which authentication is required. The domain object is unreferenced after being added. ```c SoupAuthDomain *domain; domain = soup_auth_domain_basic_new ( "realm", "My Realm", "auth-callback", auth_callback, "auth-data", auth_data, "add-path", "/foo", "add-path", "/bar/private", NULL); soup_server_add_auth_domain (server, domain); g_object_unref (domain); ``` -------------------------------- ### Include libsoup header Source: https://github.com/gnome/libsoup/blob/master/docs/reference/build-howto.md Include the main libsoup header file in your C/C++ source code. ```c #include ``` -------------------------------- ### Set minimum and maximum allowed libsoup versions with Autotools Source: https://github.com/gnome/libsoup/blob/master/docs/reference/build-howto.md Define SOUP_VERSION_MIN_REQUIRED and SOUP_VERSION_MAX_ALLOWED using CFLAGS in Autotools to control API compatibility and warnings. ```autoconf LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_3_0" LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_2" ``` -------------------------------- ### Check libsoup module with Autotools Source: https://github.com/gnome/libsoup/blob/master/docs/reference/build-howto.md Use PKG_CHECK_MODULES to find libsoup-3.0 and substitute its compiler flags and libraries for use in your Autotools build. ```autoconf PKG_CHECK_MODULES(LIBSOUP, [libsoup-3.0]) AC_SUBST(LIBSOUP_CFLAGS) AC_SUBST(LIBSOUP_LIBS) ``` -------------------------------- ### Add Session Features in libsoup Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-advanced.md Demonstrates adding session features like ContentSniffer and Logger. Use `add_feature_by_type` for features without configuration and `add_feature` for those requiring construction. ```c 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); } ``` -------------------------------- ### Copy GLib Uri Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `g_uri_copy()` to create a mutable copy of an immutable GLib.Uri, aiding in modification. ```c g_uri_copy (uri) ``` -------------------------------- ### Parse GLib Uri Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `g_uri_parse()` to create a GLib.Uri from a string. Consider using `G_URI_FLAGS_PARSE_RELAXED` for broader input acceptance. ```c g_uri_parse (uri, SOUP_HTTP_URI_FLAGS, NULL) ``` -------------------------------- ### Set Custom CA in libsoup Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-tls.md Configure a `SoupSession` to use a custom Certificate Authority (CA) by providing a `GTlsDatabase` instance created from a PEM file. This is a blocking operation. ```c { 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); } ``` -------------------------------- ### Respond with Content-Length Encoding in C Source: https://github.com/gnome/libsoup/blob/master/docs/reference/server-howto.md Use this method when the entire response body is available at once. It sets the status to OK and sends the MIME type, data, and length. ```c static void server_callback (SoupServer *server, SoupServerMessage *msg, const char *path, GHashTable *query, gpointer user_data) { MyServerData *server_data = user_data; const char *mime_type; GByteArray *body; if (soup_server_message_get_method (msg) != SOUP_METHOD_GET) { soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, NULL); return; } /* This is somewhat silly. Presumably your server will do * something more interesting. */ body = g_hash_table_lookup (server_data->bodies, path); mime_type = g_hash_table_lookup (server_data->mime_types, path); if (!body || !mime_type) { soup_server_message_set_status (msg, SOUP_STATUS_NOT_FOUND, NULL); return; } soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); soup_server_message_set_response (msg, mime_type, SOUP_MEMORY_COPY, body->data, body->len); } ``` -------------------------------- ### Send and Read Response with Session Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Convenience APIs for directly requesting and reading a response into a buffer. ```c GBytes *data = soup_session_send_and_read (session, msg, NULL); // Use data ``` -------------------------------- ### Check for OPTIONS Ping Message Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `SoupMessage:is-options-ping` property to handle OPTIONS messages with a path of `*`, which is no longer a valid URI. ```c [property@Message:is-options-ping] ``` -------------------------------- ### Read Response Body with GIOStream Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use GIOStream APIs to read response data. Previously, direct buffer access was available. ```c SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "/"); // ... configure session and send message ... GIOStream *stream = soup_message_get_response_stream (msg); // Read from stream using GIO APIs ``` -------------------------------- ### Convert GLib Uri to String Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `g_uri_to_string_partial()` with `G_URI_HIDE_PASSWORD` to convert a GLib.Uri to a string, similar to `soup_uri_to_string(uri, FALSE)`. ```c g_uri_to_string_partial (uri, G_URI_HIDE_PASSWORD) ``` -------------------------------- ### Add a Request Handler to SoupServer Source: https://github.com/gnome/libsoup/blob/master/docs/reference/server-howto.md Use this to register a callback function for specific URI paths. The handler will be invoked for requests matching the base path or its sub-paths. A NULL base path acts as a default handler. ```c soup_server_add_handler (server, "/foo", server_callback, data, destroy_notify); ``` -------------------------------- ### Accept Invalid or Pinned Certificates in libsoup Source: https://github.com/gnome/libsoup/blob/master/docs/reference/client-tls.md Use the `accept-certificate` signal on `SoupMessage` to manually control certificate validation. Returning `TRUE` bypasses standard validation, useful for development or specific trust scenarios. Ensure proper certificate inspection within the callback. ```c 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; } ``` -------------------------------- ### SoupServer Handler Callback Signature Source: https://github.com/gnome/libsoup/blob/master/docs/reference/server-howto.md This is the standard signature for a libsoup server callback function. It receives the server instance, message details, the matched path, parsed query parameters, and user-provided data. ```c static void server_callback (SoupServer *server, SoupServerMessage *msg, const char *path, GHashTable *query, gpointer user_data) { // ... } ``` -------------------------------- ### Set Request Body from Bytes Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Convenience API to set a request body from a GLib.Bytes buffer. ```c soup_message_set_request_body_from_bytes (msg, "application/json", bytes); ``` -------------------------------- ### Set SoupMessage URI Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_set_uri()` to set the URI for a SoupMessage. This replaces direct struct field access. ```c soup_message_set_uri() ``` -------------------------------- ### Set SoupMessage Request Body from Bytes Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_set_request_body_from_bytes()` to set the request body of a SoupMessage from GLib.Bytes. This replaces direct struct field access. ```c soup_message_set_request_body_from_bytes() ``` -------------------------------- ### Set SoupMessage Request Body Source: https://github.com/gnome/libsoup/blob/master/docs/reference/migrating-from-libsoup-2.md Use `soup_message_set_request_body()` to set the request body of a SoupMessage. This replaces direct struct field access. ```c soup_message_set_request_body() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.