diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2021-06-08 17:44:04 +0200 |
---|---|---|
committer | Günther Wagner <info@gunibert.de> | 2021-11-04 21:39:51 +0100 |
commit | f014c22bbb1e5dd857d6e47c5acf5f58fc28cecf (patch) | |
tree | 586b94fb13ac152e717ae454bdb841c10a87a830 /rest/rest-proxy-call.c | |
parent | e55578092e347a4fce887d5a278dc007204fa5cd (diff) | |
download | librest-f014c22bbb1e5dd857d6e47c5acf5f58fc28cecf.tar.gz |
Port to libsoup3
Diffstat (limited to 'rest/rest-proxy-call.c')
-rw-r--r-- | rest/rest-proxy-call.c | 296 |
1 files changed, 239 insertions, 57 deletions
diff --git a/rest/rest-proxy-call.c b/rest/rest-proxy-call.c index 2ab722f..62b00da 100644 --- a/rest/rest-proxy-call.c +++ b/rest/rest-proxy-call.c @@ -20,12 +20,14 @@ * */ +#include <config.h> #include <rest/rest-proxy.h> #include <rest/rest-proxy-call.h> #include <rest/rest-params.h> #include <libsoup/soup.h> #include "rest-private.h" +#include "rest-proxy-auth-private.h" #include "rest-proxy-call-private.h" @@ -38,12 +40,15 @@ struct _RestProxyCallAsyncClosure { }; typedef struct _RestProxyCallAsyncClosure RestProxyCallAsyncClosure; +#define READ_BUFFER_SIZE 8192 + struct _RestProxyCallContinuousClosure { RestProxyCall *call; RestProxyCallContinuousCallback callback; GObject *weak_object; gpointer userdata; SoupMessage *message; + guchar buffer[READ_BUFFER_SIZE]; }; typedef struct _RestProxyCallContinuousClosure RestProxyCallContinuousClosure; @@ -70,8 +75,7 @@ struct _RestProxyCallPrivate { gchar *url; GHashTable *response_headers; - goffset length; - gchar *payload; + GBytes *payload; guint status_code; gchar *status_message; @@ -160,7 +164,7 @@ rest_proxy_call_finalize (GObject *object) g_free (priv->method); g_free (priv->function); - g_free (priv->payload); + g_clear_pointer (&priv->payload, g_bytes_unref); g_free (priv->status_message); g_free (priv->url); @@ -546,14 +550,23 @@ _populate_headers_hash_table (const gchar *name, g_hash_table_insert (headers, g_strdup (name), g_strdup (value)); } +#ifdef WITH_SOUP_2 /* I apologise for this macro, but it saves typing ;-) */ #define error_helper(x) g_set_error_literal(error, REST_PROXY_ERROR, x, message->reason_phrase) +#endif static gboolean _handle_error_from_message (SoupMessage *message, GError **error) { - if (message->status_code < 100) + guint status_code; + const char *reason_phrase; + +#ifdef WITH_SOUP_2 + status_code = message->status_code; + + if (status_code < 100) { - switch (message->status_code) + g_clear_error (error); + switch (status_code) { case SOUP_STATUS_CANCELLED: error_helper (REST_PROXY_ERROR_CANCELLED); @@ -580,61 +593,84 @@ _handle_error_from_message (SoupMessage *message, GError **error) } return FALSE; } + reason_phrase = message->reason_phrase; +#else + status_code = soup_message_get_status (message); + reason_phrase = soup_message_get_reason_phrase (message); +#endif - if (message->status_code >= 200 && message->status_code < 300) + if (status_code >= 200 && status_code < 300) { return TRUE; } + if (*error != NULL) + return FALSE; + /* If we are here we must be in some kind of HTTP error, lets try */ g_set_error_literal (error, REST_PROXY_ERROR, - message->status_code, - message->reason_phrase); + status_code, + reason_phrase); return FALSE; } static gboolean -finish_call (RestProxyCall *call, SoupMessage *message, GError **error) +finish_call (RestProxyCall *call, SoupMessage *message, GBytes *payload, GError **error) { RestProxyCallPrivate *priv = GET_PRIVATE (call); + SoupMessageHeaders *response_headers; g_assert (call); g_assert (message); + g_assert (payload); + +#ifdef WITH_SOUP_2 + response_headers = message->response_headers; +#else + response_headers = soup_message_get_response_headers (message); +#endif /* Convert the soup headers in to hash */ /* FIXME: Eeek..are you allowed duplicate headers? ... */ g_hash_table_remove_all (priv->response_headers); - soup_message_headers_foreach (message->response_headers, + soup_message_headers_foreach (response_headers, (SoupMessageHeadersForeachFunc)_populate_headers_hash_table, priv->response_headers); - priv->payload = g_memdup (message->response_body->data, - message->response_body->length + 1); - priv->length = message->response_body->length; + priv->payload = payload; +#ifdef WITH_SOUP_2 priv->status_code = message->status_code; priv->status_message = g_strdup (message->reason_phrase); +#else + priv->status_code = soup_message_get_status (message); + priv->status_message = g_strdup (soup_message_get_reason_phrase (message)); +#endif return _handle_error_from_message (message, error); } static void -_continuous_call_message_completed_cb (SoupSession *session, - SoupMessage *message, - gpointer userdata) +_continuous_call_message_completed (SoupMessage *message, + GError *error, + gpointer userdata) { RestProxyCallContinuousClosure *closure; RestProxyCall *call; RestProxyCallPrivate *priv; - GError *error = NULL; closure = (RestProxyCallContinuousClosure *)userdata; call = closure->call; priv = GET_PRIVATE (call); +#ifdef WITH_SOUP_2 priv->status_code = message->status_code; priv->status_message = g_strdup (message->reason_phrase); +#else + priv->status_code = soup_message_get_status (message); + priv->status_message = g_strdup (soup_message_get_reason_phrase (message)); +#endif _handle_error_from_message (message, &error); @@ -657,6 +693,7 @@ _continuous_call_message_completed_cb (SoupSession *session, priv->cur_call_closure = NULL; g_object_unref (closure->call); + g_object_unref (message); g_slice_free (RestProxyCallContinuousClosure, closure); } @@ -715,6 +752,49 @@ set_url (RestProxyCall *call) return TRUE; } +#ifndef WITH_SOUP_2 +static gboolean +authenticate (RestProxyCall *call, + SoupAuth *soup_auth, + gboolean retrying, + SoupMessage *message) +{ + RestProxyCallPrivate *priv = GET_PRIVATE (call); + RestProxyAuth *rest_auth; + gboolean try_auth; + + rest_auth = rest_proxy_auth_new (priv->proxy, NULL, message, soup_auth); + g_signal_emit_by_name (priv->proxy, "authenticate", rest_auth, retrying, &try_auth); + if (try_auth && !rest_proxy_auth_is_paused (rest_auth)) { + char *username, *password; + + g_object_get (priv->proxy, "username", &username, "password", &password, NULL); + soup_auth_authenticate (soup_auth, username, password); + g_free (username); + g_free (password); + } + g_object_unref (rest_auth); + + return try_auth; +} + +static gboolean +accept_certificate (RestProxyCall *call, + GTlsCertificate *tls_certificate, + GTlsCertificateFlags *tls_errors, + SoupMessage *message) +{ + RestProxyCallPrivate *priv = GET_PRIVATE (call); + gboolean ssl_strict; + + if (tls_errors == 0) + return TRUE; + + g_object_get (priv->proxy, "ssl-strict", &ssl_strict, NULL); + return !ssl_strict; +} +#endif + static SoupMessage * prepare_message (RestProxyCall *call, GError **error_out) { @@ -722,6 +802,7 @@ prepare_message (RestProxyCall *call, GError **error_out) RestProxyCallClass *call_class; const gchar *user_agent; SoupMessage *message; + SoupMessageHeaders *request_headers; GError *error = NULL; call_class = REST_PROXY_CALL_GET_CLASS (call); @@ -748,6 +829,9 @@ prepare_message (RestProxyCall *call, GError **error_out) gchar *content; gchar *content_type; gsize content_len; +#ifndef WITH_SOUP_2 + GBytes *body; +#endif if (!call_class->serialize_params (call, &content_type, &content, &content_len, &error)) @@ -780,8 +864,14 @@ prepare_message (RestProxyCall *call, GError **error_out) "Could not parse URI"); return NULL; } +#ifdef WITH_SOUP_2 soup_message_set_request (message, content_type, SOUP_MEMORY_TAKE, content, content_len); +#else + body = g_bytes_new_take (content, content_len); + soup_message_set_request_body_from_bytes (message, content_type, body); + g_bytes_unref (body); +#endif g_free (content_type); } else if (rest_params_are_strings (priv->params)) { @@ -798,9 +888,15 @@ prepare_message (RestProxyCall *call, GError **error_out) hash = rest_params_as_string_hash_table (priv->params); +#ifdef WITH_SOUP_2 message = soup_form_request_new_from_hash (priv->method, priv->url, hash); +#else + message = soup_message_new_from_encoded_form (priv->method, + priv->url, + soup_form_encode_hash (hash)); +#endif g_hash_table_unref (hash); @@ -827,19 +923,28 @@ prepare_message (RestProxyCall *call, GError **error_out) if (rest_param_is_string (param)) { soup_multipart_append_form_string (mp, name, rest_param_get_content (param)); } else { - SoupBuffer *sb; - - sb = soup_buffer_new_with_owner (rest_param_get_content (param), - rest_param_get_content_length (param), - rest_param_ref (param), - (GDestroyNotify)rest_param_unref); +#ifdef WITH_SOUP_2 + SoupBuffer *sb = soup_buffer_new_with_owner (rest_param_get_content (param), + rest_param_get_content_length (param), + rest_param_ref (param), + (GDestroyNotify)rest_param_unref); +#else + GBytes *sb = g_bytes_new_with_free_func (rest_param_get_content (param), + rest_param_get_content_length (param), + (GDestroyNotify)rest_param_unref, + rest_param_ref (param)); +#endif soup_multipart_append_form_file (mp, name, rest_param_get_file_name (param), rest_param_get_content_type (param), sb); +#ifdef WITH_SOUP_2 soup_buffer_free (sb); +#else + g_bytes_unref (sb); +#endif } } @@ -853,19 +958,36 @@ prepare_message (RestProxyCall *call, GError **error_out) return NULL; } +#ifdef WITH_SOUP_2 message = soup_form_request_new_from_multipart (priv->url, mp); +#else + message = soup_message_new_from_multipart (priv->url, mp); +#endif soup_multipart_free (mp); } +#ifdef WITH_SOUP_2 + request_headers = message->request_headers; +#else + request_headers = soup_message_get_request_headers (message); + g_signal_connect_swapped (message, "authenticate", + G_CALLBACK (authenticate), + call); + g_signal_connect_swapped (message, "accept-certificate", + G_CALLBACK (accept_certificate), + call); +#endif + + /* Set the user agent, if one was set in the proxy */ user_agent = rest_proxy_get_user_agent (priv->proxy); if (user_agent) { - soup_message_headers_append (message->request_headers, "User-Agent", user_agent); + soup_message_headers_append (request_headers, "User-Agent", user_agent); } /* Set the headers */ - g_hash_table_foreach (priv->headers, set_header, message->request_headers); + g_hash_table_foreach (priv->headers, set_header, request_headers); return message; } @@ -878,17 +1000,17 @@ _call_message_call_cancelled_cb (GCancellable *cancellable, } static void -_call_message_call_completed_cb (SoupSession *session, - SoupMessage *message, +_call_message_call_completed_cb (SoupMessage *message, + GBytes *payload, + GError *error, gpointer user_data) { GTask *task = user_data; RestProxyCall *call; - GError *error = NULL; call = REST_PROXY_CALL (g_task_get_source_object (task)); - finish_call (call, message, &error); + finish_call (call, message, payload, &error); if (error != NULL) g_task_return_error (task, error); @@ -938,6 +1060,7 @@ rest_proxy_call_invoke_async (RestProxyCall *call, _rest_proxy_queue_message (priv->proxy, message, + priv->cancellable, _call_message_call_completed_cb, task); } @@ -962,16 +1085,55 @@ rest_proxy_call_invoke_finish (RestProxyCall *call, } static void -_continuous_call_message_got_chunk_cb (SoupMessage *msg, - SoupBuffer *chunk, - RestProxyCallContinuousClosure *closure) +_continuous_call_read_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) { + GInputStream *stream = G_INPUT_STREAM (source); + RestProxyCallContinuousClosure *closure = user_data; + RestProxyCallPrivate *priv = GET_PRIVATE (closure->call); + gssize bytes_read; + GError *error = NULL; + + bytes_read = g_input_stream_read_finish (stream, result, &error); + if (bytes_read <= 0) + { + _continuous_call_message_completed (closure->message, error, user_data); + return; + } + closure->callback (closure->call, - chunk->data, - chunk->length, + (gconstpointer)closure->buffer, + bytes_read, NULL, closure->weak_object, closure->userdata); + + g_input_stream_read_async (stream, closure->buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT, + priv->cancellable, _continuous_call_read_cb, closure); +} + +static void +_continuous_call_message_sent_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + RestProxy *proxy = REST_PROXY (source); + RestProxyCallContinuousClosure *closure = user_data; + RestProxyCallPrivate *priv = GET_PRIVATE (closure->call); + GInputStream *stream; + GError *error = NULL; + + stream = _rest_proxy_send_message_finish (proxy, result, &error); + if (!stream) + { + _continuous_call_message_completed (closure->message, error, user_data); + return; + } + + g_input_stream_read_async (stream, closure->buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT, + priv->cancellable, _continuous_call_read_cb, closure); + g_object_unref (stream); } @@ -1021,9 +1183,6 @@ rest_proxy_call_continuous (RestProxyCall *call, if (message == NULL) return FALSE; - /* Must turn off accumulation */ - soup_message_body_set_accumulate (message->response_body, FALSE); - closure = g_slice_new0 (RestProxyCallContinuousClosure); closure->call = g_object_ref (call); closure->callback = callback; @@ -1041,33 +1200,29 @@ rest_proxy_call_continuous (RestProxyCall *call, closure); } - g_signal_connect (message, - "got-chunk", - (GCallback)_continuous_call_message_got_chunk_cb, - closure); - - _rest_proxy_queue_message (priv->proxy, - message, - _continuous_call_message_completed_cb, - closure); + _rest_proxy_send_message_async (priv->proxy, + message, + priv->cancellable, + _continuous_call_message_sent_cb, + closure); return TRUE; } static void -_upload_call_message_completed_cb (SoupSession *session, - SoupMessage *message, +_upload_call_message_completed_cb (SoupMessage *message, + GBytes *payload, + GError *error, gpointer user_data) { RestProxyCall *call; RestProxyCallPrivate *priv; - GError *error = NULL; RestProxyCallUploadClosure *closure; closure = (RestProxyCallUploadClosure *) user_data; call = closure->call; priv = GET_PRIVATE (call); - finish_call (call, message, &error); + finish_call (call, message, payload, &error); closure->callback (closure->call, closure->uploaded, @@ -1093,14 +1248,25 @@ _upload_call_message_completed_cb (SoupSession *session, static void _upload_call_message_wrote_data_cb (SoupMessage *msg, +#ifdef WITH_SOUP_2 SoupBuffer *chunk, +#else + gsize chunk_size, +#endif RestProxyCallUploadClosure *closure) { - closure->uploaded = closure->uploaded + chunk->length; +#ifdef WITH_SOUP_2 + gsize chunk_size = chunk->length; + goffset content_length = msg->request_body->length; +#else + goffset content_length = soup_message_headers_get_content_length (soup_message_get_request_headers (msg)); +#endif - if (closure->uploaded < msg->request_body->length) + closure->uploaded = closure->uploaded + chunk_size; + + if (closure->uploaded < content_length) closure->callback (closure->call, - msg->request_body->length, + content_length, closure->uploaded, NULL, closure->weak_object, @@ -1178,6 +1344,7 @@ rest_proxy_call_upload (RestProxyCall *call, _rest_proxy_queue_message (priv->proxy, message, + priv->cancellable, _upload_call_message_completed_cb, closure); return TRUE; @@ -1206,6 +1373,10 @@ rest_proxy_call_cancel (RestProxyCall *call) if (priv->cancellable) { g_signal_handler_disconnect (priv->cancellable, priv->cancel_sig); +#ifndef WITH_SOUP_2 + if (!g_cancellable_is_cancelled (priv->cancellable)) + g_cancellable_cancel (priv->cancellable); +#endif g_clear_object (&priv->cancellable); } @@ -1240,6 +1411,7 @@ rest_proxy_call_sync (RestProxyCall *call, RestProxyCallPrivate *priv = GET_PRIVATE (call); SoupMessage *message; gboolean ret; + GBytes *payload; g_return_val_if_fail (REST_IS_PROXY_CALL (call), FALSE); @@ -1247,9 +1419,9 @@ rest_proxy_call_sync (RestProxyCall *call, if (!message) return FALSE; - _rest_proxy_send_message (priv->proxy, message); + payload = _rest_proxy_send_message (priv->proxy, message, priv->cancellable, error_out); - ret = finish_call (call, message, error_out); + ret = finish_call (call, message, payload, error_out); g_object_unref (message); @@ -1314,9 +1486,16 @@ rest_proxy_call_get_response_headers (RestProxyCall *call) goffset rest_proxy_call_get_payload_length (RestProxyCall *call) { + GBytes *payload; + g_return_val_if_fail (REST_IS_PROXY_CALL (call), 0); - return GET_PRIVATE (call)->length; + payload = GET_PRIVATE (call)->payload; +#ifdef WITH_SOUP_2 + return payload ? g_bytes_get_size (payload) - 1 : 0; +#else + return payload ? g_bytes_get_size (payload) : 0; +#endif } /** @@ -1331,9 +1510,12 @@ rest_proxy_call_get_payload_length (RestProxyCall *call) const gchar * rest_proxy_call_get_payload (RestProxyCall *call) { + GBytes *payload; + g_return_val_if_fail (REST_IS_PROXY_CALL (call), NULL); - return GET_PRIVATE (call)->payload; + payload = GET_PRIVATE (call)->payload; + return payload ? g_bytes_get_data (payload, NULL) : NULL; } /** |