summaryrefslogtreecommitdiff
path: root/rest/rest-proxy-call.c
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2021-06-08 17:44:04 +0200
committerGünther Wagner <info@gunibert.de>2021-11-04 21:39:51 +0100
commitf014c22bbb1e5dd857d6e47c5acf5f58fc28cecf (patch)
tree586b94fb13ac152e717ae454bdb841c10a87a830 /rest/rest-proxy-call.c
parente55578092e347a4fce887d5a278dc007204fa5cd (diff)
downloadlibrest-f014c22bbb1e5dd857d6e47c5acf5f58fc28cecf.tar.gz
Port to libsoup3
Diffstat (limited to 'rest/rest-proxy-call.c')
-rw-r--r--rest/rest-proxy-call.c296
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;
}
/**