summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-11-19 15:59:36 -0600
committerPatrick Griffis <tingping@tingping.se>2020-12-13 19:32:41 +0000
commit05c0418ae7dd458bb989ad26d54bda96aace31ae (patch)
treefcf3890d2cc9bcc9c16f3021b7984cdda237f789
parentc04594785cc427426e95bbe744a55166de69d9d5 (diff)
downloadlibsoup-05c0418ae7dd458bb989ad26d54bda96aace31ae.tar.gz
Rewrite get example using new API
-rw-r--r--examples/get.c228
-rw-r--r--examples/meson.build4
-rw-r--r--meson.build3
3 files changed, 143 insertions, 92 deletions
diff --git a/examples/get.c b/examples/get.c
index 377cf854..5b8dd244 100644
--- a/examples/get.c
+++ b/examples/get.c
@@ -18,79 +18,112 @@ static GMainLoop *loop;
static gboolean debug, head, quiet;
static const gchar *output_file_path = NULL;
+#define OUTPUT_BUFFER_SIZE 8192
+
static void
-finished (SoupSession *session, SoupMessage *msg, gpointer loop)
+on_stream_splice (GObject *source, GAsyncResult *result, gpointer user_data)
{
- g_main_loop_quit (loop);
+ GError *error = NULL;
+ g_output_stream_splice_finish (G_OUTPUT_STREAM (source),
+ result,
+ &error);
+ if (error) {
+ g_printerr ("Failed to download: %s\n", error->message);
+ g_error_free (error);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ g_main_loop_quit (loop);
}
static void
-get_url (const char *url)
+on_read_ready (GObject *source, GAsyncResult *result, gpointer user_data)
{
- const char *name;
- SoupMessage *msg;
- const char *header;
- FILE *output_file = NULL;
-
- msg = soup_message_new (head ? "HEAD" : "GET", url);
- soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-
- g_object_ref (msg);
- soup_session_queue_message (session, msg, finished, loop);
- g_main_loop_run (loop);
-
- name = g_uri_get_path (soup_message_get_uri (msg));
-
- if (!debug) {
- if (soup_message_get_status (msg) == SOUP_STATUS_SSL_FAILED) {
- GTlsCertificateFlags flags;
-
- if (soup_message_get_https_status (msg, NULL, &flags))
- g_print ("%s: %d %s (0x%x)\n", name, soup_message_get_status (msg), soup_message_get_reason_phrase (msg), flags);
- else
- g_print ("%s: %d %s (no handshake status)\n", name, soup_message_get_status (msg), soup_message_get_reason_phrase (msg));
- } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (soup_message_get_status (msg)))
- g_print ("%s: %d %s\n", name, soup_message_get_status (msg), soup_message_get_reason_phrase (msg));
- }
+ GInputStream *in = G_INPUT_STREAM (source);
+ GError *error = NULL;
+ gsize bytes_read = 0;
+ char *output_buffer = user_data;
+
+ g_input_stream_read_all_finish (in, result, &bytes_read, &error);
+
+ if (bytes_read) {
+ g_print ("%.*s", (int)bytes_read, output_buffer);
+ }
+
+ if (error) {
+ g_printerr ("\nFailed to read stream: %s\n", error->message);
+ g_error_free (error);
+ g_free (output_buffer);
+ g_main_loop_quit (loop);
+ } else if (!bytes_read) {
+ g_print ("\n");
+ g_free (output_buffer);
+ g_main_loop_quit (loop);
+ } else {
+ g_input_stream_read_all_async (in, output_buffer, OUTPUT_BUFFER_SIZE,
+ G_PRIORITY_DEFAULT, NULL, on_read_ready, output_buffer);
+ }
+}
- if (SOUP_STATUS_IS_REDIRECTION (soup_message_get_status (msg))) {
- header = soup_message_headers_get_one (soup_message_get_response_headers (msg),
- "Location");
- if (header) {
- GUri *uri;
- char *uri_string;
-
- if (!debug && !quiet)
- g_print (" -> %s\n", header);
-
- uri = g_uri_parse_relative (soup_message_get_uri (msg), header, SOUP_HTTP_URI_FLAGS, NULL);
- g_assert (uri != NULL);
- uri_string = g_uri_to_string (uri);
- get_url (uri_string);
- g_free (uri_string);
- g_uri_unref (uri);
- }
- } else if (!head && SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) {
- if (output_file_path) {
- output_file = fopen (output_file_path, "w");
- if (!output_file)
- g_printerr ("Error trying to create file %s.\n", output_file_path);
- } else if (!quiet)
- output_file = stdout;
-
- if (output_file) {
- fwrite (msg->response_body->data,
- 1,
- msg->response_body->length,
- output_file);
-
- if (output_file_path)
- fclose (output_file);
- }
- }
- g_object_unref (msg);
+static void
+on_request_sent (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GError *error = NULL;
+ SoupMessage *msg = user_data;
+ GInputStream *in = soup_session_send_finish (SOUP_SESSION (source), result, &error);
+
+ if (error) {
+ g_printerr ("Failed to send request: %s\n", error->message);
+ g_error_free (error);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ if (!debug) {
+ const char *path = g_uri_get_path (soup_message_get_uri (msg));
+ g_print ("%s: %d %s\n", path, soup_message_get_status (msg),
+ soup_message_get_reason_phrase (msg));
+ }
+
+ if (head || !SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (msg))) {
+ g_object_unref (in);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ if (output_file_path) {
+ GFile *output_file = g_file_new_for_commandline_arg (output_file_path);
+ GOutputStream *out = G_OUTPUT_STREAM (g_file_create (output_file, G_FILE_CREATE_NONE,
+ NULL, &error));
+ if (error) {
+ g_print ("Failed to create \"%s\": %s\n", output_file_path, error->message);
+ g_error_free (error);
+ g_object_unref (in);
+ g_object_unref (output_file);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ /* Start downloading to the file */
+ g_output_stream_splice_async (G_OUTPUT_STREAM (out), in,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ on_stream_splice,
+ NULL);
+
+ g_object_unref (out);
+ } else {
+ char *output_buffer = g_new (char, OUTPUT_BUFFER_SIZE);
+ g_input_stream_read_all_async (in, output_buffer, OUTPUT_BUFFER_SIZE,
+ G_PRIORITY_DEFAULT, NULL, on_read_ready, output_buffer);
+ }
+
+ g_object_unref (in);
}
+
/* Inline class for providing a pre-configured client certificate */
typedef struct _GetTlsCertInteraction GetTlsCertInteraction;
typedef struct _GetTlsCertInteractionClass GetTlsCertInteractionClass;
@@ -191,10 +224,9 @@ main (int argc, char **argv)
{
GOptionContext *opts;
const char *url;
- GUri *proxy_uri, *parsed;
+ GUri *parsed;
+ SoupMessage *msg;
GError *error = NULL;
- SoupLogger *logger = NULL;
- char *help;
opts = g_option_context_new (NULL);
g_option_context_add_main_entries (opts, entries, NULL);
@@ -209,13 +241,14 @@ main (int argc, char **argv)
}
if (argc != 2) {
- help = g_option_context_get_help (opts, TRUE, NULL);
+ char *help = g_option_context_get_help (opts, TRUE, NULL);
g_printerr ("%s", help);
g_free (help);
exit (1);
}
g_option_context_free (opts);
+ /* Validate the URL */
url = argv[1];
parsed = g_uri_parse (url, SOUP_HTTP_URI_FLAGS, &error);
if (!parsed) {
@@ -224,27 +257,47 @@ main (int argc, char **argv)
}
g_uri_unref (parsed);
- session = g_object_new (SOUP_TYPE_SESSION,
- "user-agent", "get ",
- "accept-language-auto", TRUE,
- NULL);
+ /* Build the session with all of the features we need */
+ session = soup_session_new_with_options ("user-agent", "get ",
+ "accept-language-auto", TRUE,
+ "timeout", 15,
+ NULL);
soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR);
if (ntlm)
soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM);
- if (ca_file)
- g_object_set (session, "ssl-ca-file", ca_file, NULL);
+#ifdef LIBSOUP_HAVE_GSSAPI
+ if (negotiate)
+ soup_session_add_feature_by_type (session,
+ SOUP_TYPE_AUTH_NEGOTIATE);
+#endif
+
+ if (ca_file) {
+ GTlsDatabase *tls_db = g_tls_file_database_new (ca_file, &error);
+ if (error) {
+ g_printerr ("Failed to load TLS database \"%s\": %s", ca_file, error->message);
+ g_error_free (error);
+ g_object_unref (session);
+ exit (1);
+ }
+
+ g_object_set (session, "tls-database", tls_db, NULL);
+ g_object_unref (tls_db);
+ }
if (client_cert_file) {
GTlsCertificate *client_cert;
GetTlsCertInteraction *interaction;
if (!client_key_file) {
g_printerr ("--key is required with --cert\n");
+ g_object_unref (session);
exit (1);
}
client_cert = g_tls_certificate_new_from_files (client_cert_file, client_key_file, &error);
if (!client_cert) {
g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ g_object_unref (session);
exit (1);
}
interaction = _get_tls_cert_interaction_new (client_cert);
@@ -252,19 +305,19 @@ main (int argc, char **argv)
}
if (debug) {
- logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
+ SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_HEADERS);
soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
g_object_unref (logger);
}
if (proxy) {
GProxyResolver *resolver;
- GError *error;
- proxy_uri = g_uri_parse (proxy, SOUP_HTTP_URI_FLAGS, &error);
+ GUri *proxy_uri = g_uri_parse (proxy, SOUP_HTTP_URI_FLAGS, &error);
if (!proxy_uri) {
g_printerr ("Could not parse '%s' as URI: %s\n",
proxy, error->message);
g_error_free (error);
+ g_object_unref (session);
exit (1);
}
@@ -276,20 +329,19 @@ main (int argc, char **argv)
g_object_unref (resolver);
}
-#ifdef LIBSOUP_HAVE_GSSAPI
- if (negotiate) {
- soup_session_add_feature_by_type (session,
- SOUP_TYPE_AUTH_NEGOTIATE);
- }
-#endif /* LIBSOUP_HAVE_GSSAPI */
-
- loop = g_main_loop_new (NULL, TRUE);
-
- get_url (url);
+ /* Send the message */
+ msg = soup_message_new (head ? "HEAD" : "GET", url);
+ /* Note that soup_session_read_uri_async() and soup_session_load_uri_bytes_async()
+ are more simple APIs for common usage. This is a lower level example using
+ SoupMessage */
+ soup_session_send_async (session, msg, G_PRIORITY_DEFAULT, NULL, on_request_sent, msg);
+ /* Run the loop */
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
g_main_loop_unref (loop);
-
g_object_unref (session);
+ g_object_unref (msg);
return 0;
}
diff --git a/examples/meson.build b/examples/meson.build
index a553aac3..75dbf45e 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -5,8 +5,8 @@ deps = [
examples = [
'get',
- 'simple-httpd',
- 'simple-proxy'
+ # 'simple-httpd',
+ # FIXME: 'simple-proxy'
]
foreach example: examples
diff --git a/meson.build b/meson.build
index f7e8981b..6564856c 100644
--- a/meson.build
+++ b/meson.build
@@ -355,8 +355,7 @@ if find_program('xgettext', required : false).found()
subdir('po')
endif
-# FIXME: port examples to use the new API.
-#subdir('examples')
+subdir('examples')
if get_option('tests')
subdir('tests')