| From 3dc630ae5b9dc6cda1ba318de2cd654aaba7b4a2 Mon Sep 17 00:00:00 2001 |
| From: Carlos Garcia Campos <cgarcia@igalia.com> |
| Date: Tue, 8 Jun 2021 17:44:04 +0200 |
| Subject: [PATCH 2/2] Port to libsoup3 |
| |
| Upstream-Status: Submitted [https://gitlab.gnome.org/GNOME/librest/-/merge_requests/6] |
| --- |
| configure.ac | 39 ++++- |
| rest-extras.pc.in | 2 +- |
| rest-extras/youtube-proxy.c | 110 +++++++++++--- |
| rest.pc.in | 2 +- |
| rest/rest-private.h | 22 ++- |
| rest/rest-proxy-auth.c | 16 ++ |
| rest/rest-proxy-call.c | 296 +++++++++++++++++++++++++++++------- |
| rest/rest-proxy.c | 209 ++++++++++++++++++++++--- |
| tests/custom-serialize.c | 18 +++ |
| tests/proxy-continuous.c | 37 ++++- |
| tests/proxy.c | 63 +++++++- |
| tests/threaded.c | 17 +++ |
| 12 files changed, 719 insertions(+), 112 deletions(-) |
| |
| diff --git a/configure.ac b/configure.ac |
| index d586e69..75c02fe 100644 |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -20,12 +20,6 @@ AM_INIT_AUTOMAKE([1.11 foreign -Wno-portability no-define dist-xz]) |
| |
| AM_SILENT_RULES([yes]) |
| |
| -API_MAJOR=1 |
| -API_MINOR=0 |
| -AC_SUBST([API_VERSION],[$API_MAJOR.$API_MINOR]) |
| -AC_SUBST([API_VERSION_AM],[$API_MAJOR\_$API_MINOR]) |
| -AC_DEFINE_UNQUOTED(API_VERSION, [$API_VERSION], [API version]) |
| - |
| AC_CANONICAL_HOST |
| |
| AC_PROG_CC |
| @@ -41,7 +35,6 @@ LT_PREREQ([2.2.6]) |
| LT_INIT([disable-static]) |
| |
| PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.67.4) |
| -PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.42) |
| PKG_CHECK_MODULES(XML, libxml-2.0) |
| PKG_CHECK_MODULES(GTHREAD, gthread-2.0) |
| |
| @@ -58,6 +51,37 @@ AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums]) |
| localedir=${datadir}/locale |
| AC_SUBST(localedir) |
| |
| +AC_MSG_CHECKING([for libsoup version to use]) |
| +AC_ARG_WITH(soup, |
| + [AC_HELP_STRING([--soup=2|3], |
| + [version of libsoup library to use (default: 2)])], |
| + [case "$withval" in |
| + 2|3) ;; |
| + *) AC_MSG_ERROR([invalid argument "$withval" for --with-soup]) ;; |
| + esac], |
| + [with_soup=2]) |
| +AC_MSG_RESULT([$with_soup]) |
| + |
| +API_MAJOR=1 |
| + |
| +if test "$with_soup" = "2"; then |
| + PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.42) |
| + SOUP_API_VERSION=2.4 |
| + API_MINOR=0 |
| + AC_DEFINE([WITH_SOUP_2],[1],[Define if libsoup version used is 2]) |
| +else |
| + PKG_CHECK_MODULES(SOUP, libsoup-3.0 >= 2.99.8) |
| + SOUP_API_VERSION=3.0 |
| + API_MINOR=1 |
| +fi |
| + |
| +AM_CONDITIONAL([WITH_SOUP_2],[test "$with_soup" = "2"]) |
| +AC_SUBST(SOUP_API_VERSION) |
| + |
| +AC_SUBST([API_VERSION],[$API_MAJOR.$API_MINOR]) |
| +AC_SUBST([API_VERSION_AM],[$API_MAJOR\_$API_MINOR]) |
| +AC_DEFINE_UNQUOTED(API_VERSION, [$API_VERSION], [API version]) |
| + |
| dnl === Coverage report ======================================================= |
| AC_PATH_PROG([GCOV], [lcov], [enable_gcov=no]) |
| |
| @@ -130,6 +154,7 @@ echo " LibRest $VERSION" |
| echo " ================" |
| echo "" |
| echo " prefix: ${prefix}" |
| +echo " libsoup version: ${with_soup}" |
| echo "" |
| echo " Documentation: ${enable_gtk_doc}" |
| echo " Introspection data: ${enable_introspection}" |
| diff --git a/rest-extras.pc.in b/rest-extras.pc.in |
| index 39f21bf..3723d6d 100644 |
| --- a/rest-extras.pc.in |
| +++ b/rest-extras.pc.in |
| @@ -9,4 +9,4 @@ Description: RESTful web api query library |
| Version: @VERSION@ |
| Libs: -L${libdir} -lrest-extras-${apiversion} |
| Cflags: -I${includedir}/rest-${apiversion} |
| -Requires: glib-2.0 libsoup-2.4 libxml-2.0 |
| +Requires: glib-2.0 libsoup-@SOUP_API_VERSION@ libxml-2.0 |
| diff --git a/rest-extras/youtube-proxy.c b/rest-extras/youtube-proxy.c |
| index be0cf08..cd598f4 100644 |
| --- a/rest-extras/youtube-proxy.c |
| +++ b/rest-extras/youtube-proxy.c |
| @@ -246,6 +246,9 @@ typedef struct { |
| GObject *weak_object; |
| gpointer user_data; |
| gsize uploaded; |
| +#ifndef WITH_SOUP_2 |
| + GCancellable *cancellable; |
| +#endif |
| } YoutubeProxyUploadClosure; |
| |
| static void |
| @@ -255,7 +258,11 @@ _upload_async_weak_notify_cb (gpointer *data, |
| YoutubeProxyUploadClosure *closure = |
| (YoutubeProxyUploadClosure *) data; |
| |
| +#ifdef WITH_SOUP_2 |
| _rest_proxy_cancel_message (REST_PROXY (closure->proxy), closure->message); |
| +#else |
| + g_cancellable_cancel (closure->cancellable); |
| +#endif |
| } |
| |
| static void |
| @@ -267,6 +274,9 @@ _upload_async_closure_free (YoutubeProxyUploadClosure *closure) |
| closure); |
| |
| g_object_unref (closure->proxy); |
| +#ifndef WITH_SOUP_2 |
| + g_object_unref (closure->cancellable); |
| +#endif |
| |
| g_slice_free (YoutubeProxyUploadClosure, closure); |
| } |
| @@ -286,6 +296,9 @@ _upload_async_closure_new (YoutubeProxy *self, |
| closure->message = message; |
| closure->weak_object = weak_object; |
| closure->user_data = user_data; |
| +#ifndef WITH_SOUP_2 |
| + closure->cancellable = g_cancellable_new (); |
| +#endif |
| |
| if (weak_object != NULL) |
| g_object_weak_ref (weak_object, |
| @@ -295,41 +308,67 @@ _upload_async_closure_new (YoutubeProxy *self, |
| } |
| |
| static void |
| -_upload_completed_cb (SoupSession *session, |
| - SoupMessage *message, |
| +_upload_completed_cb (SoupMessage *message, |
| + GBytes *payload, |
| + GError *error, |
| gpointer user_data) |
| { |
| YoutubeProxyUploadClosure *closure = |
| (YoutubeProxyUploadClosure *) user_data; |
| - GError *error = NULL; |
| + gsize length; |
| + gconstpointer data; |
| + guint status_code; |
| + const char *reason_phrase; |
| |
| if (closure->callback == NULL) |
| return; |
| |
| - if (message->status_code < 200 || message->status_code >= 300) |
| - error = g_error_new_literal (REST_PROXY_ERROR, |
| - message->status_code, |
| - message->reason_phrase); |
| - |
| - closure->callback (closure->proxy, message->response_body->data, |
| - message->request_body->length, |
| - message->request_body->length, |
| +#ifdef WITH_SOUP_2 |
| + status_code = message->status_code; |
| + reason_phrase = message->reason_phrase; |
| +#else |
| + status_code = soup_message_get_status (message); |
| + reason_phrase = soup_message_get_reason_phrase (message); |
| +#endif |
| + |
| + if (status_code < 200 || status_code >= 300) |
| + { |
| + g_clear_error (&error); |
| + error = g_error_new_literal (REST_PROXY_ERROR, |
| + status_code, |
| + reason_phrase); |
| + } |
| + |
| + data = g_bytes_get_data (payload, &length); |
| + closure->callback (closure->proxy, data, length, length, |
| error, closure->weak_object, closure->user_data); |
| + g_bytes_unref (payload); |
| |
| _upload_async_closure_free (closure); |
| } |
| |
| static void |
| _message_wrote_data_cb (SoupMessage *msg, |
| +#ifdef WITH_SOUP_2 |
| SoupBuffer *chunk, |
| +#else |
| + gsize chunk_size, |
| +#endif |
| YoutubeProxyUploadClosure *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 |
| + |
| + closure->uploaded = closure->uploaded + chunk_size; |
| |
| - if (closure->uploaded < msg->request_body->length) |
| + if (closure->uploaded < content_length) |
| closure->callback (closure->proxy, |
| NULL, |
| - msg->request_body->length, |
| + content_length, |
| closure->uploaded, |
| NULL, |
| closure->weak_object, |
| @@ -364,7 +403,12 @@ youtube_proxy_upload_async (YoutubeProxy *self, |
| SoupMultipart *mp; |
| SoupMessage *message; |
| SoupMessageHeaders *part_headers; |
| + SoupMessageHeaders *request_headers; |
| +#ifdef WITH_SOUP_2 |
| SoupBuffer *sb; |
| +#else |
| + GBytes *sb; |
| +#endif |
| gchar *content_type; |
| gchar *atom_xml; |
| GMappedFile *map; |
| @@ -380,10 +424,17 @@ youtube_proxy_upload_async (YoutubeProxy *self, |
| |
| atom_xml = _construct_upload_atom_xml (fields, incomplete); |
| |
| +#ifdef WITH_SOUP_2 |
| sb = soup_buffer_new_with_owner (atom_xml, |
| strlen(atom_xml), |
| atom_xml, |
| (GDestroyNotify) g_free); |
| +#else |
| + sb = g_bytes_new_with_free_func (atom_xml, |
| + strlen (atom_xml), |
| + (GDestroyNotify) g_free, |
| + atom_xml); |
| +#endif |
| |
| part_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); |
| |
| @@ -393,7 +444,11 @@ youtube_proxy_upload_async (YoutubeProxy *self, |
| |
| soup_multipart_append_part (mp, part_headers, sb); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_buffer_free (sb); |
| +#else |
| + g_bytes_unref (sb); |
| +#endif |
| |
| content_type = g_content_type_guess ( |
| filename, |
| @@ -401,24 +456,37 @@ youtube_proxy_upload_async (YoutubeProxy *self, |
| g_mapped_file_get_length (map), |
| NULL); |
| |
| +#ifdef WITH_SOUP_2 |
| sb = soup_buffer_new_with_owner (g_mapped_file_get_contents (map), |
| g_mapped_file_get_length (map), |
| map, |
| (GDestroyNotify) g_mapped_file_unref); |
| +#else |
| + sb = g_bytes_new_with_free_func (g_mapped_file_get_contents (map), |
| + g_mapped_file_get_length (map), |
| + (GDestroyNotify) g_mapped_file_unref, |
| + map); |
| +#endif |
| |
| soup_message_headers_replace (part_headers, "Content-Type", content_type); |
| |
| soup_multipart_append_part (mp, part_headers, sb); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_buffer_free (sb); |
| - |
| soup_message_headers_free (part_headers); |
| - |
| message = soup_form_request_new_from_multipart (UPLOAD_URL, mp); |
| + request_headers = message->request_headers; |
| +#else |
| + g_bytes_unref (sb); |
| + soup_message_headers_unref (part_headers); |
| + message = soup_message_new_from_multipart (UPLOAD_URL, mp); |
| + request_headers = soup_message_get_request_headers (message); |
| +#endif |
| |
| soup_multipart_free (mp); |
| |
| - _set_upload_headers (self, message->request_headers, filename); |
| + _set_upload_headers (self, request_headers, filename); |
| |
| closure = _upload_async_closure_new (self, callback, message, weak_object, |
| user_data); |
| @@ -429,7 +497,13 @@ youtube_proxy_upload_async (YoutubeProxy *self, |
| closure); |
| |
| |
| - _rest_proxy_queue_message (REST_PROXY (self), message, _upload_completed_cb, |
| + _rest_proxy_queue_message (REST_PROXY (self), message, |
| +#ifdef WITH_SOUP_2 |
| + NULL, |
| +#else |
| + closure->cancellable, |
| +#endif |
| + _upload_completed_cb, |
| closure); |
| |
| return TRUE; |
| diff --git a/rest.pc.in b/rest.pc.in |
| index 94c384b..e6bae3e 100644 |
| --- a/rest.pc.in |
| +++ b/rest.pc.in |
| @@ -9,4 +9,4 @@ Description: RESTful web api query library |
| Version: @VERSION@ |
| Libs: -L${libdir} -lrest-${apiversion} |
| Cflags: -I${includedir}/rest-${apiversion} |
| -Requires: glib-2.0 libsoup-2.4 libxml-2.0 |
| +Requires: glib-2.0 libsoup-@SOUP_API_VERSION@ libxml-2.0 |
| diff --git a/rest/rest-private.h b/rest/rest-private.h |
| index 9e91fa0..6e71322 100644 |
| --- a/rest/rest-private.h |
| +++ b/rest/rest-private.h |
| @@ -31,6 +31,11 @@ |
| |
| G_BEGIN_DECLS |
| |
| +typedef void (*RestMessageFinishedCallback) (SoupMessage *msg, |
| + GBytes *body, |
| + GError *error, |
| + gpointer user_data); |
| + |
| typedef enum |
| { |
| REST_DEBUG_XML_PARSER = 1 << 0, |
| @@ -53,12 +58,23 @@ gboolean _rest_proxy_get_binding_required (RestProxy *proxy); |
| const gchar *_rest_proxy_get_bound_url (RestProxy *proxy); |
| void _rest_proxy_queue_message (RestProxy *proxy, |
| SoupMessage *message, |
| - SoupSessionCallback callback, |
| + GCancellable *cancellable, |
| + RestMessageFinishedCallback callback, |
| gpointer user_data); |
| void _rest_proxy_cancel_message (RestProxy *proxy, |
| SoupMessage *message); |
| -guint _rest_proxy_send_message (RestProxy *proxy, |
| - SoupMessage *message); |
| +GBytes *_rest_proxy_send_message (RestProxy *proxy, |
| + SoupMessage *message, |
| + GCancellable *cancellable, |
| + GError **error); |
| +void _rest_proxy_send_message_async (RestProxy *proxy, |
| + SoupMessage *message, |
| + GCancellable *cancellable, |
| + GAsyncReadyCallback callback, |
| + gpointer user_data); |
| +GInputStream *_rest_proxy_send_message_finish (RestProxy *proxy, |
| + GAsyncResult *result, |
| + GError **error); |
| |
| RestXmlNode *_rest_xml_node_new (void); |
| void _rest_xml_node_reverse_children_siblings (RestXmlNode *node); |
| diff --git a/rest/rest-proxy-auth.c b/rest/rest-proxy-auth.c |
| index b96e443..0b2ec9f 100644 |
| --- a/rest/rest-proxy-auth.c |
| +++ b/rest/rest-proxy-auth.c |
| @@ -29,7 +29,9 @@ |
| struct _RestProxyAuthPrivate { |
| /* used to hold state during async authentication */ |
| RestProxy *proxy; |
| +#ifdef WITH_SOUP_2 |
| SoupSession *session; |
| +#endif |
| SoupMessage *message; |
| SoupAuth *auth; |
| gboolean paused; |
| @@ -43,7 +45,9 @@ rest_proxy_auth_dispose (GObject *object) |
| RestProxyAuthPrivate *priv = ((RestProxyAuth*)object)->priv; |
| |
| g_clear_object (&priv->proxy); |
| +#ifdef WITH_SOUP_2 |
| g_clear_object (&priv->session); |
| +#endif |
| g_clear_object (&priv->message); |
| g_clear_object (&priv->auth); |
| |
| @@ -73,13 +77,17 @@ rest_proxy_auth_new (RestProxy *proxy, |
| RestProxyAuth *rest_auth; |
| |
| g_return_val_if_fail (REST_IS_PROXY (proxy), NULL); |
| +#ifdef WITH_SOUP_2 |
| g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); |
| +#endif |
| g_return_val_if_fail (SOUP_IS_MESSAGE (message), NULL); |
| g_return_val_if_fail (SOUP_IS_AUTH (soup_auth), NULL); |
| |
| rest_auth = REST_PROXY_AUTH (g_object_new (REST_TYPE_PROXY_AUTH, NULL)); |
| rest_auth->priv->proxy = g_object_ref(proxy); |
| +#ifdef WITH_SOUP_2 |
| rest_auth->priv->session = g_object_ref(session); |
| +#endif |
| rest_auth->priv->message = g_object_ref(message); |
| rest_auth->priv->auth = g_object_ref(soup_auth); |
| |
| @@ -104,7 +112,9 @@ rest_proxy_auth_pause (RestProxyAuth *auth) |
| return; |
| |
| auth->priv->paused = TRUE; |
| +#ifdef WITH_SOUP_2 |
| soup_session_pause_message (auth->priv->session, auth->priv->message); |
| +#endif |
| } |
| |
| /** |
| @@ -128,7 +138,9 @@ rest_proxy_auth_unpause (RestProxyAuth *auth) |
| soup_auth_authenticate (auth->priv->auth, username, password); |
| g_free (username); |
| g_free (password); |
| +#ifdef WITH_SOUP_2 |
| soup_session_unpause_message (auth->priv->session, auth->priv->message); |
| +#endif |
| auth->priv->paused = FALSE; |
| } |
| |
| @@ -146,7 +158,11 @@ rest_proxy_auth_cancel (RestProxyAuth *auth) |
| { |
| g_return_if_fail (REST_IS_PROXY_AUTH (auth)); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_session_cancel_message (auth->priv->session, auth->priv->message, SOUP_STATUS_CANCELLED); |
| +#else |
| + soup_auth_cancel (auth->priv->auth); |
| +#endif |
| } |
| |
| G_GNUC_INTERNAL gboolean rest_proxy_auth_is_paused (RestProxyAuth *auth) |
| 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; |
| } |
| |
| /** |
| diff --git a/rest/rest-proxy.c b/rest/rest-proxy.c |
| index 80972a3..171f6cb 100644 |
| --- a/rest/rest-proxy.c |
| +++ b/rest/rest-proxy.c |
| @@ -45,6 +45,9 @@ struct _RestProxyPrivate { |
| SoupSession *session; |
| gboolean disable_cookies; |
| char *ssl_ca_file; |
| +#ifndef WITH_SOUP_2 |
| + gboolean ssl_strict; |
| +#endif |
| }; |
| |
| |
| @@ -116,11 +119,15 @@ rest_proxy_get_property (GObject *object, |
| g_value_set_string (value, priv->password); |
| break; |
| case PROP_SSL_STRICT: { |
| +#ifdef WITH_SOUP_2 |
| gboolean ssl_strict; |
| g_object_get (G_OBJECT(priv->session), |
| "ssl-strict", &ssl_strict, |
| NULL); |
| g_value_set_boolean (value, ssl_strict); |
| +#else |
| + g_value_set_boolean (value, priv->ssl_strict); |
| +#endif |
| break; |
| } |
| case PROP_SSL_CA_FILE: |
| @@ -172,9 +179,13 @@ rest_proxy_set_property (GObject *object, |
| priv->password = g_value_dup_string (value); |
| break; |
| case PROP_SSL_STRICT: |
| +#ifdef WITH_SOUP_2 |
| g_object_set (G_OBJECT(priv->session), |
| "ssl-strict", g_value_get_boolean (value), |
| NULL); |
| +#else |
| + priv->ssl_strict = g_value_get_boolean (value); |
| +#endif |
| break; |
| case PROP_SSL_CA_FILE: |
| g_free(priv->ssl_ca_file); |
| @@ -207,6 +218,7 @@ default_authenticate_cb (RestProxy *self, |
| return !retrying; |
| } |
| |
| +#ifdef WITH_SOUP_2 |
| static void |
| authenticate (RestProxy *self, |
| SoupMessage *msg, |
| @@ -224,6 +236,7 @@ authenticate (RestProxy *self, |
| soup_auth_authenticate (soup_auth, priv->username, priv->password); |
| g_object_unref (G_OBJECT (rest_auth)); |
| } |
| +#endif |
| |
| static void |
| rest_proxy_constructed (GObject *object) |
| @@ -238,14 +251,20 @@ rest_proxy_constructed (GObject *object) |
| } |
| |
| if (REST_DEBUG_ENABLED(PROXY)) { |
| +#ifdef WITH_SOUP_2 |
| SoupSessionFeature *logger = (SoupSessionFeature*)soup_logger_new (SOUP_LOGGER_LOG_BODY, 0); |
| +#else |
| + SoupSessionFeature *logger = (SoupSessionFeature*)soup_logger_new (SOUP_LOGGER_LOG_HEADERS); |
| +#endif |
| soup_session_add_feature (priv->session, logger); |
| g_object_unref (logger); |
| } |
| |
| +#ifdef WITH_SOUP_2 |
| /* session lifetime is same as self, no need to keep signalid */ |
| g_signal_connect_swapped (priv->session, "authenticate", |
| G_CALLBACK(authenticate), object); |
| +#endif |
| } |
| |
| static void |
| @@ -391,23 +410,62 @@ rest_proxy_class_init (RestProxyClass *klass) |
| proxy_class->authenticate = default_authenticate_cb; |
| } |
| |
| +static gboolean |
| +transform_ssl_ca_file_to_tls_database (GBinding *binding, |
| + const GValue *from_value, |
| + GValue *to_value, |
| + gpointer user_data) |
| +{ |
| + g_value_take_object (to_value, |
| + g_tls_file_database_new (g_value_get_string (from_value), NULL)); |
| + return TRUE; |
| +} |
| + |
| +static gboolean |
| +transform_tls_database_to_ssl_ca_file (GBinding *binding, |
| + const GValue *from_value, |
| + GValue *to_value, |
| + gpointer user_data) |
| +{ |
| + GTlsDatabase *tls_database; |
| + char *path = NULL; |
| + |
| + tls_database = g_value_get_object (from_value); |
| + if (tls_database) |
| + g_object_get (tls_database, "anchors", &path, NULL); |
| + g_value_take_string (to_value, path); |
| + return TRUE; |
| +} |
| + |
| static void |
| rest_proxy_init (RestProxy *self) |
| { |
| RestProxyPrivate *priv = GET_PRIVATE (self); |
| + GTlsDatabase *tls_database; |
| + |
| +#ifndef WITH_SOUP_2 |
| + priv->ssl_strict = TRUE; |
| +#endif |
| |
| priv->session = soup_session_new (); |
| |
| #ifdef REST_SYSTEM_CA_FILE |
| /* with ssl-strict (defaults TRUE) setting ssl-ca-file forces all |
| * certificates to be trusted */ |
| - g_object_set (priv->session, |
| - "ssl-ca-file", REST_SYSTEM_CA_FILE, |
| - NULL); |
| + tls_database = g_tls_file_database_new (REST_SYSTEM_CA_FILE, NULL); |
| + if (tls_database) { |
| + g_object_set (priv->session, |
| + "tls-database", tls_database, |
| + NULL); |
| + g_object_unref (tls_database); |
| + } |
| #endif |
| - g_object_bind_property (self, "ssl-ca-file", |
| - priv->session, "ssl-ca-file", |
| - G_BINDING_BIDIRECTIONAL); |
| + g_object_bind_property_full (self, "ssl-ca-file", |
| + priv->session, "tls-database", |
| + G_BINDING_BIDIRECTIONAL, |
| + transform_ssl_ca_file_to_tls_database, |
| + transform_tls_database_to_ssl_ca_file, |
| + NULL, NULL); |
| } |
| |
| /** |
| @@ -689,27 +747,127 @@ rest_proxy_simple_run (RestProxy *proxy, |
| return ret; |
| } |
| |
| +typedef struct { |
| + RestMessageFinishedCallback callback; |
| + gpointer user_data; |
| +} RestMessageQueueData; |
| + |
| +#ifdef WITH_SOUP_2 |
| +static void |
| +message_finished_cb (SoupSession *session, |
| + SoupMessage *message, |
| + gpointer user_data) |
| +{ |
| + RestMessageQueueData *data = user_data; |
| + GBytes *body; |
| + GError *error = NULL; |
| + |
| + body = g_bytes_new (message->response_body->data, |
| + message->response_body->length + 1); |
| + data->callback (message, body, error, data->user_data); |
| + g_free (data); |
| +} |
| +#else |
| +static void |
| +message_send_and_read_ready_cb (GObject *source, |
| + GAsyncResult *result, |
| + gpointer user_data) |
| +{ |
| + SoupSession *session = SOUP_SESSION (source); |
| + RestMessageQueueData *data = user_data; |
| + GBytes *body; |
| + GError *error = NULL; |
| + |
| + body = soup_session_send_and_read_finish (session, result, &error); |
| + data->callback (soup_session_get_async_result_message (session, result), body, error, data->user_data); |
| + g_free (data); |
| +} |
| +#endif |
| + |
| void |
| -_rest_proxy_queue_message (RestProxy *proxy, |
| - SoupMessage *message, |
| - SoupSessionCallback callback, |
| - gpointer user_data) |
| +_rest_proxy_queue_message (RestProxy *proxy, |
| + SoupMessage *message, |
| + GCancellable *cancellable, |
| + RestMessageFinishedCallback callback, |
| + gpointer user_data) |
| { |
| RestProxyPrivate *priv = GET_PRIVATE (proxy); |
| + RestMessageQueueData *data; |
| |
| g_return_if_fail (REST_IS_PROXY (proxy)); |
| g_return_if_fail (SOUP_IS_MESSAGE (message)); |
| |
| + data = g_new0 (RestMessageQueueData, 1); |
| + data->callback = callback; |
| + data->user_data = user_data; |
| + |
| +#ifdef WITH_SOUP_2 |
| soup_session_queue_message (priv->session, |
| message, |
| - callback, |
| - user_data); |
| + message_finished_cb, |
| + data); |
| +#else |
| + soup_session_send_and_read_async (priv->session, |
| + message, |
| + G_PRIORITY_DEFAULT, |
| + cancellable, |
| + message_send_and_read_ready_cb, |
| + data); |
| +#endif |
| +} |
| + |
| +static void |
| +message_send_ready_cb (GObject *source, |
| + GAsyncResult *result, |
| + gpointer user_data) |
| +{ |
| + SoupSession *session = SOUP_SESSION (source); |
| + GTask *task = user_data; |
| + GInputStream *stream; |
| + GError *error = NULL; |
| + |
| + stream = soup_session_send_finish (session, result, &error); |
| + if (stream) |
| + g_task_return_pointer (task, stream, g_object_unref); |
| + else |
| + g_task_return_error (task, error); |
| + g_object_unref (task); |
| +} |
| + |
| +void |
| +_rest_proxy_send_message_async (RestProxy *proxy, |
| + SoupMessage *message, |
| + GCancellable *cancellable, |
| + GAsyncReadyCallback callback, |
| + gpointer user_data) |
| +{ |
| + RestProxyPrivate *priv = GET_PRIVATE (proxy); |
| + GTask *task; |
| + |
| + task = g_task_new (proxy, cancellable, callback, user_data); |
| + soup_session_send_async (priv->session, |
| + message, |
| +#ifndef WITH_SOUP_2 |
| + G_PRIORITY_DEFAULT, |
| +#endif |
| + cancellable, |
| + message_send_ready_cb, |
| + task); |
| +} |
| + |
| +GInputStream * |
| +_rest_proxy_send_message_finish (RestProxy *proxy, |
| + GAsyncResult *result, |
| + GError **error) |
| +{ |
| + return g_task_propagate_pointer (G_TASK (result), error); |
| } |
| |
| void |
| _rest_proxy_cancel_message (RestProxy *proxy, |
| SoupMessage *message) |
| { |
| +#ifdef WITH_SOUP_2 |
| RestProxyPrivate *priv = GET_PRIVATE (proxy); |
| |
| g_return_if_fail (REST_IS_PROXY (proxy)); |
| @@ -718,16 +876,31 @@ _rest_proxy_cancel_message (RestProxy *proxy, |
| soup_session_cancel_message (priv->session, |
| message, |
| SOUP_STATUS_CANCELLED); |
| +#endif |
| } |
| |
| -guint |
| -_rest_proxy_send_message (RestProxy *proxy, |
| - SoupMessage *message) |
| +GBytes * |
| +_rest_proxy_send_message (RestProxy *proxy, |
| + SoupMessage *message, |
| + GCancellable *cancellable, |
| + GError **error) |
| { |
| RestProxyPrivate *priv = GET_PRIVATE (proxy); |
| + GBytes *body; |
| |
| - g_return_val_if_fail (REST_IS_PROXY (proxy), 0); |
| - g_return_val_if_fail (SOUP_IS_MESSAGE (message), 0); |
| + g_return_val_if_fail (REST_IS_PROXY (proxy), NULL); |
| + g_return_val_if_fail (SOUP_IS_MESSAGE (message), NULL); |
| + |
| +#ifdef WITH_SOUP_2 |
| + soup_session_send_message (priv->session, message); |
| + body = g_bytes_new (message->response_body->data, |
| + message->response_body->length + 1); |
| +#else |
| + body = soup_session_send_and_read (priv->session, |
| + message, |
| + cancellable, |
| + error); |
| +#endif |
| |
| - return soup_session_send_message (priv->session, message); |
| + return body; |
| } |
| diff --git a/tests/custom-serialize.c b/tests/custom-serialize.c |
| index c3fde93..01b3a56 100644 |
| --- a/tests/custom-serialize.c |
| +++ b/tests/custom-serialize.c |
| @@ -88,22 +88,40 @@ custom_proxy_call_init (CustomProxyCall *self) |
| } |
| |
| static void |
| +#ifdef WITH_SOUP_2 |
| server_callback (SoupServer *server, SoupMessage *msg, |
| const char *path, GHashTable *query, |
| SoupClientContext *client, gpointer user_data) |
| +#else |
| +server_callback (SoupServer *server, SoupServerMessage *msg, |
| + const char *path, GHashTable *query, gpointer user_data) |
| +#endif |
| { |
| if (g_str_equal (path, "/ping")) { |
| const char *content_type = NULL; |
| +#ifdef WITH_SOUP_2 |
| SoupMessageHeaders *headers = msg->request_headers; |
| SoupMessageBody *body = msg->request_body; |
| +#else |
| + SoupMessageHeaders *headers = soup_server_message_get_request_headers (msg); |
| + SoupMessageBody *body = soup_server_message_get_request_body (msg); |
| +#endif |
| content_type = soup_message_headers_get_content_type (headers, NULL); |
| g_assert_cmpstr (content_type, ==, "application/json"); |
| |
| g_assert_cmpstr (body->data, ==, "{}"); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } else { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, NULL); |
| +#endif |
| } |
| } |
| |
| diff --git a/tests/proxy-continuous.c b/tests/proxy-continuous.c |
| index 8f4b7a8..7967bbd 100644 |
| --- a/tests/proxy-continuous.c |
| +++ b/tests/proxy-continuous.c |
| @@ -39,9 +39,15 @@ static SoupServer *server; |
| static gboolean |
| send_chunks (gpointer user_data) |
| { |
| - SoupMessage *msg = SOUP_MESSAGE (user_data); |
| guint i; |
| guint8 data[SIZE_CHUNK]; |
| +#ifdef WITH_SOUP_2 |
| + SoupMessage *msg = SOUP_MESSAGE (user_data); |
| + SoupMessageBody *response_body = msg->response_body; |
| +#else |
| + SoupServerMessage *msg = SOUP_SERVER_MESSAGE (user_data); |
| + SoupMessageBody *response_body = soup_server_message_get_response_body (msg); |
| +#endif |
| |
| for (i = 0; i < SIZE_CHUNK; i++) |
| { |
| @@ -49,12 +55,12 @@ send_chunks (gpointer user_data) |
| server_count++; |
| } |
| |
| - soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, data, SIZE_CHUNK); |
| + soup_message_body_append (response_body, SOUP_MEMORY_COPY, data, SIZE_CHUNK); |
| soup_server_unpause_message (server, msg); |
| |
| if (server_count == NUM_CHUNKS * SIZE_CHUNK) |
| { |
| - soup_message_body_complete (msg->response_body); |
| + soup_message_body_complete (response_body); |
| return FALSE; |
| } else { |
| return TRUE; |
| @@ -62,13 +68,28 @@ send_chunks (gpointer user_data) |
| } |
| |
| static void |
| +#ifdef WITH_SOUP_2 |
| server_callback (SoupServer *server, SoupMessage *msg, |
| const char *path, GHashTable *query, |
| SoupClientContext *client, gpointer user_data) |
| +#else |
| +server_callback (SoupServer *server, SoupServerMessage *msg, |
| + const char *path, GHashTable *query, gpointer user_data) |
| +#endif |
| { |
| +#ifdef WITH_SOUP_2 |
| + SoupMessageHeaders *response_headers = msg->response_headers; |
| +#else |
| + SoupMessageHeaders *response_headers = soup_server_message_get_response_headers (msg); |
| +#endif |
| + |
| g_assert_cmpstr (path, ==, "/stream"); |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| - soup_message_headers_set_encoding (msg->response_headers, |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| + soup_message_headers_set_encoding (response_headers, |
| SOUP_ENCODING_CHUNKED); |
| soup_server_pause_message (server, msg); |
| |
| @@ -142,13 +163,21 @@ continuous () |
| uris = soup_server_get_uris (server); |
| g_assert (g_slist_length (uris) > 0); |
| |
| +#ifdef WITH_SOUP_2 |
| url = soup_uri_to_string (uris->data, FALSE); |
| +#else |
| + url = g_uri_to_string (uris->data); |
| +#endif |
| |
| loop = g_main_loop_new (NULL, FALSE); |
| |
| proxy = rest_proxy_new (url, FALSE); |
| stream_test (proxy); |
| +#ifdef WITH_SOUP_2 |
| g_slist_free_full (uris, (GDestroyNotify)soup_uri_free); |
| +#else |
| + g_slist_free_full (uris, (GDestroyNotify)g_uri_unref); |
| +#endif |
| |
| g_main_loop_run (loop); |
| g_free (url); |
| diff --git a/tests/proxy.c b/tests/proxy.c |
| index 89a9325..652c600 100644 |
| --- a/tests/proxy.c |
| +++ b/tests/proxy.c |
| @@ -49,20 +49,35 @@ SoupServer *server; |
| GMainLoop *server_loop; |
| |
| static void |
| +#ifdef WITH_SOUP_2 |
| server_callback (SoupServer *server, SoupMessage *msg, |
| const char *path, GHashTable *query, |
| SoupClientContext *client, gpointer user_data) |
| +#else |
| +server_callback (SoupServer *server, SoupServerMessage *msg, |
| + const char *path, GHashTable *query, gpointer user_data) |
| +#endif |
| { |
| if (g_str_equal (path, "/ping")) { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } |
| else if (g_str_equal (path, "/echo")) { |
| const char *value; |
| |
| value = g_hash_table_lookup (query, "value"); |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, |
| value, strlen (value)); |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, |
| + value, strlen (value)); |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } |
| else if (g_str_equal (path, "/reverse")) { |
| char *value; |
| @@ -70,9 +85,15 @@ server_callback (SoupServer *server, SoupMessage *msg, |
| value = g_strdup (g_hash_table_lookup (query, "value")); |
| g_strreverse (value); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE, |
| value, strlen (value)); |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE, |
| + value, strlen (value)); |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } |
| else if (g_str_equal (path, "/status")) { |
| const char *value; |
| @@ -81,25 +102,61 @@ server_callback (SoupServer *server, SoupMessage *msg, |
| value = g_hash_table_lookup (query, "status"); |
| if (value) { |
| status = atoi (value); |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR); |
| +#else |
| + soup_server_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL); |
| +#endif |
| } else { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL); |
| +#endif |
| } |
| } |
| else if (g_str_equal (path, "/useragent/none")) { |
| - if (soup_message_headers_get (msg->request_headers, "User-Agent") == NULL) { |
| +#ifdef WITH_SOUP_2 |
| + SoupMessageHeaders *request_headers = msg->request_headers; |
| +#else |
| + SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg); |
| +#endif |
| + |
| + if (soup_message_headers_get (request_headers, "User-Agent") == NULL) { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } else { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED, NULL); |
| +#endif |
| } |
| } |
| else if (g_str_equal (path, "/useragent/testsuite")) { |
| +#ifdef WITH_SOUP_2 |
| + SoupMessageHeaders *request_headers = msg->request_headers; |
| +#else |
| + SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg); |
| +#endif |
| const char *value; |
| - value = soup_message_headers_get (msg->request_headers, "User-Agent"); |
| + value = soup_message_headers_get (request_headers, "User-Agent"); |
| if (g_strcmp0 (value, "TestSuite-1.0") == 0) { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| } else { |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED, NULL); |
| +#endif |
| + |
| } |
| } |
| } |
| @@ -325,7 +382,7 @@ main (int argc, char **argv) |
| char *url; |
| RestProxy *proxy; |
| |
| - server = soup_server_new ("", NULL); |
| + server = soup_server_new (NULL); |
| g_thread_new ("Server Thread", server_thread_func, NULL); |
| |
| url = g_strdup_printf ("http://127.0.0.1:%d/", PORT); |
| diff --git a/tests/threaded.c b/tests/threaded.c |
| index a251900..411361c 100644 |
| --- a/tests/threaded.c |
| +++ b/tests/threaded.c |
| @@ -36,13 +36,22 @@ GMainLoop *main_loop; |
| SoupServer *server; |
| |
| static void |
| +#ifdef WITH_SOUP_2 |
| server_callback (SoupServer *server, SoupMessage *msg, |
| const char *path, GHashTable *query, |
| SoupClientContext *client, gpointer user_data) |
| +#else |
| +server_callback (SoupServer *server, SoupServerMessage *msg, |
| + const char *path, GHashTable *query, gpointer user_data) |
| +#endif |
| { |
| g_assert_cmpstr (path, ==, "/ping"); |
| |
| +#ifdef WITH_SOUP_2 |
| soup_message_set_status (msg, SOUP_STATUS_OK); |
| +#else |
| + soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL); |
| +#endif |
| g_atomic_int_add (&threads_done, 1); |
| |
| if (threads_done == N_THREADS) { |
| @@ -96,7 +105,11 @@ static void ping () |
| uris = soup_server_get_uris (server); |
| g_assert (g_slist_length (uris) > 0); |
| |
| +#ifdef WITH_SOUP_2 |
| url = soup_uri_to_string (uris->data, FALSE); |
| +#else |
| + url = g_uri_to_string (uris->data); |
| +#endif |
| |
| main_loop = g_main_loop_new (NULL, TRUE); |
| |
| @@ -109,7 +122,11 @@ static void ping () |
| g_main_loop_run (main_loop); |
| |
| g_free (url); |
| +#ifdef WITH_SOUP_2 |
| g_slist_free_full (uris, (GDestroyNotify)soup_uri_free); |
| +#else |
| + g_slist_free_full (uris, (GDestroyNotify)g_uri_unref); |
| +#endif |
| g_object_unref (server); |
| g_main_loop_unref (main_loop); |
| } |
| -- |
| 2.33.1 |
| |