summary refs log tree commit diff
path: root/src/nm-cloud-setup/nm-http-client.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2023-06-12 11:25:29 +0200
committerMichael Biebl <biebl@debian.org>2023-06-12 11:25:29 +0200
commit150fe9eef8dd22307ee16687509acde616663982 (patch)
tree200fa1178c9aeee2ff874bb63afe93623da4be0d /src/nm-cloud-setup/nm-http-client.c
parentdfaaf221cfee4ffcc507d793dae051d402646679 (diff)
New upstream version 1.42.6 upstream/1.42.6
Diffstat (limited to 'src/nm-cloud-setup/nm-http-client.c')
-rw-r--r--src/nm-cloud-setup/nm-http-client.c161
1 files changed, 87 insertions, 74 deletions
diff --git a/src/nm-cloud-setup/nm-http-client.c b/src/nm-cloud-setup/nm-http-client.c
index a0964e21..db123f10 100644
--- a/src/nm-cloud-setup/nm-http-client.c
+++ b/src/nm-cloud-setup/nm-http-client.c
@@ -104,12 +104,12 @@ typedef struct {
 } GetResult;
 
 static void
-_get_result_free(gpointer data)
+_req_result_free(gpointer data)
 {
-    GetResult *get_result = data;
+    GetResult *req_result = data;
 
-    g_bytes_unref(get_result->response_data);
-    nm_g_slice_free(get_result);
+    g_bytes_unref(req_result->response_data);
+    nm_g_slice_free(req_result);
 }
 
 typedef struct {
@@ -154,7 +154,7 @@ _ehandle_free(EHandleData *edata)
 static void
 _ehandle_complete(EHandleData *edata, GError *error_take)
 {
-    GetResult    *get_result;
+    GetResult    *req_result;
     gs_free char *str_tmp_1     = NULL;
     long          response_code = -1;
 
@@ -200,15 +200,15 @@ _ehandle_complete(EHandleData *edata, GError *error_take)
 
     _ehandle_free_ehandle(edata);
 
-    get_result  = g_slice_new(GetResult);
-    *get_result = (GetResult){
+    req_result  = g_slice_new(GetResult);
+    *req_result = (GetResult){
         .response_code = response_code,
         /* This ensures that response_data is always NUL terminated. This is an important guarantee
          * that NMHttpClient makes. */
         .response_data = nm_str_buf_finalize_to_gbytes(&edata->recv_data),
     };
 
-    g_task_return_pointer(edata->task, get_result, _get_result_free);
+    g_task_return_pointer(edata->task, req_result, _req_result_free);
 
     _ehandle_free(edata);
 }
@@ -256,12 +256,13 @@ _get_cancelled_cb(GObject *object, gpointer user_data)
     _ehandle_complete(edata, error);
 }
 
-void
-nm_http_client_get(NMHttpClient       *self,
+static void
+nm_http_client_req(NMHttpClient       *self,
                    const char         *url,
                    int                 timeout_msec,
                    gssize              max_data,
                    const char *const  *http_headers,
+                   const char         *http_method,
                    GCancellable       *cancellable,
                    GAsyncReadyCallback callback,
                    gpointer            user_data)
@@ -280,7 +281,7 @@ nm_http_client_get(NMHttpClient       *self,
 
     edata  = g_slice_new(EHandleData);
     *edata = (EHandleData){
-        .task      = nm_g_task_new(self, cancellable, nm_http_client_get, callback, user_data),
+        .task      = nm_g_task_new(self, cancellable, nm_http_client_req, callback, user_data),
         .recv_data = NM_STR_BUF_INIT(0, FALSE),
         .max_data  = max_data,
         .url       = g_strdup(url),
@@ -289,7 +290,7 @@ nm_http_client_get(NMHttpClient       *self,
 
     nmcs_wait_for_objects_register(edata->task);
 
-    _LOG2D(edata, "start get ...");
+    _LOG2D(edata, "start %s ...", http_method ?: "get");
 
     edata->ehandle = curl_easy_init();
     if (!edata->ehandle) {
@@ -328,6 +329,9 @@ nm_http_client_get(NMHttpClient       *self,
         curl_easy_setopt(edata->ehandle, CURLOPT_HTTPHEADER, edata->headers);
     }
 
+    if (http_method)
+        curl_easy_setopt(edata->ehandle, CURLOPT_CUSTOMREQUEST, http_method);
+
     if (timeout_msec > 0) {
         edata->timeout_source = _source_attach(self,
                                                nm_g_timeout_source_new(timeout_msec,
@@ -352,7 +356,7 @@ nm_http_client_get(NMHttpClient       *self,
 }
 
 /**
- * nm_http_client_get_finish:
+ * nm_http_client_req_finish:
  * @self: the #NMHttpClient instance
  * @result: the #GAsyncResult which to complete.
  * @out_response_code: (allow-none) (out): the HTTP response code or -1 on other error.
@@ -366,34 +370,34 @@ nm_http_client_get(NMHttpClient       *self,
  *
  * Returns: %TRUE on success or %FALSE with an error code.
  */
-gboolean
-nm_http_client_get_finish(NMHttpClient *self,
+static gboolean
+nm_http_client_req_finish(NMHttpClient *self,
                           GAsyncResult *result,
                           long         *out_response_code,
                           GBytes      **out_response_data,
                           GError      **error)
 {
-    GetResult *get_result;
+    GetResult *req_result;
 
     g_return_val_if_fail(NM_IS_HTTP_CLIENT(self), FALSE);
-    g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_get), FALSE);
+    g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_req), FALSE);
 
-    get_result = g_task_propagate_pointer(G_TASK(result), error);
+    req_result = g_task_propagate_pointer(G_TASK(result), error);
 
-    nm_assert(!error || (!!get_result) == (!*error));
+    nm_assert(!error || (!!req_result) == (!*error));
 
-    if (!get_result) {
+    if (!req_result) {
         NM_SET_OUT(out_response_code, -1);
         NM_SET_OUT(out_response_data, NULL);
         return FALSE;
     }
 
-    NM_SET_OUT(out_response_code, get_result->response_code);
+    NM_SET_OUT(out_response_code, req_result->response_code);
 
     /* response_data is binary, but is also guaranteed to be NUL terminated! */
-    NM_SET_OUT(out_response_data, g_steal_pointer(&get_result->response_data));
+    NM_SET_OUT(out_response_data, g_steal_pointer(&req_result->response_data));
 
-    _get_result_free(get_result);
+    _req_result_free(req_result);
     return TRUE;
 }
 
@@ -403,63 +407,65 @@ typedef struct {
     GTask                      *task;
     char                       *uri;
     const char *const          *http_headers;
-    NMHttpClientPollGetCheckFcn check_fcn;
+    const char                 *http_method;
+    NMHttpClientPollReqCheckFcn check_fcn;
     gpointer                    check_user_data;
     GBytes                     *response_data;
     gsize                       request_max_data;
     long                        response_code;
     int                         request_timeout_ms;
-} PollGetData;
+} PollReqData;
 
 static void
-_poll_get_data_free(gpointer data)
+_poll_req_data_free(gpointer data)
 {
-    PollGetData *poll_get_data = data;
+    PollReqData *poll_req_data = data;
 
-    g_free(poll_get_data->uri);
+    g_free(poll_req_data->uri);
 
-    nm_clear_pointer(&poll_get_data->response_data, g_bytes_unref);
-    g_strfreev((char **) poll_get_data->http_headers);
+    nm_clear_pointer(&poll_req_data->response_data, g_bytes_unref);
+    g_free((gpointer) poll_req_data->http_headers);
 
-    nm_g_slice_free(poll_get_data);
+    nm_g_slice_free(poll_req_data);
 }
 
 static void
-_poll_get_probe_start_fcn(GCancellable       *cancellable,
+_poll_req_probe_start_fcn(GCancellable       *cancellable,
                           gpointer            probe_user_data,
                           GAsyncReadyCallback callback,
                           gpointer            user_data)
 {
-    PollGetData *poll_get_data = probe_user_data;
+    PollReqData *poll_req_data = probe_user_data;
 
-    /* balanced by _poll_get_probe_finish_fcn() */
-    g_object_ref(poll_get_data->task);
+    /* balanced by _poll_req_probe_finish_fcn() */
+    g_object_ref(poll_req_data->task);
 
-    nm_http_client_get(g_task_get_source_object(poll_get_data->task),
-                       poll_get_data->uri,
-                       poll_get_data->request_timeout_ms,
-                       poll_get_data->request_max_data,
-                       poll_get_data->http_headers,
+    nm_http_client_req(g_task_get_source_object(poll_req_data->task),
+                       poll_req_data->uri,
+                       poll_req_data->request_timeout_ms,
+                       poll_req_data->request_max_data,
+                       poll_req_data->http_headers,
+                       poll_req_data->http_method,
                        cancellable,
                        callback,
                        user_data);
 }
 
 static gboolean
-_poll_get_probe_finish_fcn(GObject      *source,
+_poll_req_probe_finish_fcn(GObject      *source,
                            GAsyncResult *result,
                            gpointer      probe_user_data,
                            GError      **error)
 {
-    PollGetData                      *poll_get_data = probe_user_data;
+    PollReqData                      *poll_req_data = probe_user_data;
     _nm_unused gs_unref_object GTask *task =
-        poll_get_data->task; /* balance ref from _poll_get_probe_start_fcn() */
+        poll_req_data->task; /* balance ref from _poll_req_probe_start_fcn() */
     gboolean               success;
     gs_free_error GError  *local_error   = NULL;
     gs_unref_bytes GBytes *response_data = NULL;
     long                   response_code = -1;
 
-    success = nm_http_client_get_finish(g_task_get_source_object(poll_get_data->task),
+    success = nm_http_client_req_finish(g_task_get_source_object(poll_req_data->task),
                                         result,
                                         &response_code,
                                         &response_data,
@@ -476,10 +482,10 @@ _poll_get_probe_finish_fcn(GObject      *source,
         return FALSE;
     }
 
-    if (poll_get_data->check_fcn) {
-        success = poll_get_data->check_fcn(response_code,
+    if (poll_req_data->check_fcn) {
+        success = poll_req_data->check_fcn(response_code,
                                            response_data,
-                                           poll_get_data->check_user_data,
+                                           poll_req_data->check_user_data,
                                            &local_error);
     } else
         success = (response_code == 200);
@@ -494,15 +500,15 @@ _poll_get_probe_finish_fcn(GObject      *source,
         return FALSE;
     }
 
-    poll_get_data->response_code = response_code;
-    poll_get_data->response_data = g_steal_pointer(&response_data);
+    poll_req_data->response_code = response_code;
+    poll_req_data->response_data = g_steal_pointer(&response_data);
     return TRUE;
 }
 
 static void
-_poll_get_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
+_poll_req_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
 {
-    PollGetData          *poll_get_data = user_data;
+    PollReqData          *poll_req_data = user_data;
     gs_free_error GError *error         = NULL;
     gboolean              success;
 
@@ -511,29 +517,30 @@ _poll_get_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
     nm_assert((!!success) == (!error));
 
     if (error)
-        g_task_return_error(poll_get_data->task, g_steal_pointer(&error));
+        g_task_return_error(poll_req_data->task, g_steal_pointer(&error));
     else
-        g_task_return_boolean(poll_get_data->task, TRUE);
+        g_task_return_boolean(poll_req_data->task, TRUE);
 
-    g_object_unref(poll_get_data->task);
+    g_object_unref(poll_req_data->task);
 }
 
 void
-nm_http_client_poll_get(NMHttpClient               *self,
+nm_http_client_poll_req(NMHttpClient               *self,
                         const char                 *uri,
                         int                         request_timeout_ms,
                         gssize                      request_max_data,
                         int                         poll_timeout_ms,
                         int                         ratelimit_timeout_ms,
                         const char *const          *http_headers,
+                        const char                 *http_method,
                         GCancellable               *cancellable,
-                        NMHttpClientPollGetCheckFcn check_fcn,
+                        NMHttpClientPollReqCheckFcn check_fcn,
                         gpointer                    check_user_data,
                         GAsyncReadyCallback         callback,
                         gpointer                    user_data)
 {
     nm_auto_pop_gmaincontext GMainContext *context = NULL;
-    PollGetData                           *poll_get_data;
+    PollReqData                           *poll_req_data;
 
     g_return_if_fail(NM_IS_HTTP_CLIENT(self));
     g_return_if_fail(uri && uri[0]);
@@ -543,21 +550,27 @@ nm_http_client_poll_get(NMHttpClient               *self,
     g_return_if_fail(ratelimit_timeout_ms >= -1);
     g_return_if_fail(!cancellable || G_CANCELLABLE(cancellable));
 
-    poll_get_data  = g_slice_new(PollGetData);
-    *poll_get_data = (PollGetData){
-        .task = nm_g_task_new(self, cancellable, nm_http_client_poll_get, callback, user_data),
+    poll_req_data  = g_slice_new(PollReqData);
+    *poll_req_data = (PollReqData){
+        .task = nm_g_task_new(self, cancellable, nm_http_client_poll_req, callback, user_data),
         .uri  = g_strdup(uri),
         .request_timeout_ms = request_timeout_ms,
         .request_max_data   = request_max_data,
         .check_fcn          = check_fcn,
         .check_user_data    = check_user_data,
         .response_code      = -1,
-        .http_headers       = NM_CAST_STRV_CC(g_strdupv((char **) http_headers)),
+        .http_headers       = NULL,
+        .http_method        = http_method,
     };
 
-    nmcs_wait_for_objects_register(poll_get_data->task);
+    if (http_headers) {
+        poll_req_data->http_headers =
+            nm_strv_dup_packed(http_headers, -1) ?: g_new(const char *, 1);
+    }
+
+    nmcs_wait_for_objects_register(poll_req_data->task);
 
-    g_task_set_task_data(poll_get_data->task, poll_get_data, _poll_get_data_free);
+    g_task_set_task_data(poll_req_data->task, poll_req_data, _poll_req_data_free);
 
     context =
         nm_g_main_context_push_thread_default_if_necessary(nm_http_client_get_main_context(self));
@@ -565,28 +578,28 @@ nm_http_client_poll_get(NMHttpClient               *self,
     nmcs_utils_poll(poll_timeout_ms,
                     ratelimit_timeout_ms,
                     0,
-                    _poll_get_probe_start_fcn,
-                    _poll_get_probe_finish_fcn,
-                    poll_get_data,
+                    _poll_req_probe_start_fcn,
+                    _poll_req_probe_finish_fcn,
+                    poll_req_data,
                     cancellable,
-                    _poll_get_done_cb,
-                    poll_get_data);
+                    _poll_req_done_cb,
+                    poll_req_data);
 }
 
 gboolean
-nm_http_client_poll_get_finish(NMHttpClient *self,
+nm_http_client_poll_req_finish(NMHttpClient *self,
                                GAsyncResult *result,
                                long         *out_response_code,
                                GBytes      **out_response_data,
                                GError      **error)
 {
-    PollGetData          *poll_get_data;
+    PollReqData          *poll_req_data;
     GTask                *task;
     gboolean              success;
     gs_free_error GError *local_error = NULL;
 
     g_return_val_if_fail(NM_HTTP_CLIENT(self), FALSE);
-    g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_poll_get), FALSE);
+    g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_poll_req), FALSE);
 
     task = G_TASK(result);
 
@@ -601,10 +614,10 @@ nm_http_client_poll_get_finish(NMHttpClient *self,
         return FALSE;
     }
 
-    poll_get_data = g_task_get_task_data(task);
+    poll_req_data = g_task_get_task_data(task);
 
-    NM_SET_OUT(out_response_code, poll_get_data->response_code);
-    NM_SET_OUT(out_response_data, g_steal_pointer(&poll_get_data->response_data));
+    NM_SET_OUT(out_response_code, poll_req_data->response_code);
+    NM_SET_OUT(out_response_data, g_steal_pointer(&poll_req_data->response_data));
     return TRUE;
 }