]> git.ipfire.org Git - pakfire.git/commitdiff
buildservice: Handle API errors correctly
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 19 Oct 2023 20:33:10 +0000 (20:33 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 19 Oct 2023 20:33:10 +0000 (20:33 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/buildservice.c

index f2643fa7eb9dc8fff0059a4d8e90c7d173e92ba7..bff778eeeefdc4c36fb6428b0e27ffbb43088cab 100644 (file)
@@ -208,6 +208,96 @@ ERROR:
        return r;
 }
 
+static int pakfire_buildservice_handle_error(struct pakfire_buildservice* service,
+               struct pakfire_transfer* transfer, const struct json_object* error) {
+       struct json_object* message = NULL;
+       struct json_object* code = NULL;
+       const char* m = NULL;
+       unsigned int c = 0;
+
+       // Fetch the URL
+       const char* url = pakfire_downloader_transfer_get_effective_url(transfer);
+
+       // Fetch the code
+       if (!json_object_object_get_ex(error, "code", &code))
+               return -EBADMSG;
+
+       // Check if the code is an integer
+       if (!json_object_is_type(code, json_type_int))
+               return -EBADMSG;
+
+       // Fetch the message
+       if (!json_object_object_get_ex(error, "message", &message))
+               return -EBADMSG;
+
+       // Check if the message is a string
+       if (!json_object_is_type(message, json_type_string))
+               return -EBADMSG;
+
+       c = json_object_get_uint64(code);
+       m = json_object_get_string(message);
+
+       // Log the error
+       CTX_ERROR(service->ctx, "%s responded with error %u:\n  %s\n", url, c, m);
+
+       // Translate the codes
+       switch (c) {
+               case 400:
+                       return -EINVAL;
+
+               default:
+                       break;
+       }
+
+       return 1;
+}
+
+/*
+       This function parses an API response
+*/
+static int pakfire_buildservice_parse_response(struct pakfire_buildservice* service,
+               struct pakfire_transfer* transfer, const char* buffer, const size_t length,
+               struct json_object** object) {
+       struct json_object* error = NULL;
+       struct json_object* o = NULL;
+       int r;
+
+       // XXX Maybe fetch the parser's error message here?!
+
+       // Parse the buffer
+       o = pakfire_json_parse(service->ctx, buffer, length);
+       if (!o) {
+               CTX_ERROR(service->ctx, "Could not parse the response\n");
+               r = -EBADMSG;
+               goto ERROR;
+       }
+
+       // Check if the response is a dictionary
+       if (!json_object_is_type(o, json_type_object)) {
+               CTX_ERROR(service->ctx, "The received object is not a JSON dict\n");
+               r = -EBADMSG;
+               goto ERROR;
+       }
+
+       // Fetch error
+       r = json_object_object_get_ex(o, "error", &error);
+       if (r) {
+               r = pakfire_buildservice_handle_error(service, transfer, error);
+               goto ERROR;
+       }
+
+       // Return the object
+       *object = o;
+
+       return 0;
+
+ERROR:
+       if (o)
+               json_object_put(o);
+
+       return r;
+}
+
 // Uploads
 
 static int pakfire_buildservice_create_upload(struct pakfire_buildservice* service,
@@ -285,11 +375,10 @@ static int pakfire_buildservice_create_upload(struct pakfire_buildservice* servi
        if (r)
                goto ERROR;
 
-       // Parse the JSON response
-       response = pakfire_json_parse(service->ctx, buffer, length);
-       if (!response) {
-               CTX_ERROR(service->ctx, "Could not parse response\n");
-               r = -EBADMSG;
+       // Parse the response
+       r = pakfire_buildservice_parse_response(service, transfer, buffer, length, &response);
+       if (r) {
+               CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
                goto ERROR;
        }
 
@@ -335,6 +424,9 @@ ERROR:
 static int pakfire_buildservice_upload_payload(struct pakfire_buildservice* service,
                const char* filename, const char* uuid, FILE* f) {
        struct pakfire_transfer* transfer = NULL;
+       struct json_object* response = NULL;
+       char* buffer = NULL;
+       size_t length = 0;
        char url[PATH_MAX];
        int r;
 
@@ -358,14 +450,28 @@ static int pakfire_buildservice_upload_payload(struct pakfire_buildservice* serv
        if (r)
                goto ERROR;
 
+       // Set the output buffer
+       r = pakfire_downloader_transfer_set_output_buffer(transfer, &buffer, &length);
+       if (r)
+               goto ERROR;
+
        // Run the transfer
        r = pakfire_downloader_transfer_run(transfer, 0);
        if (r)
                goto ERROR;
 
+       // Parse the response
+       r = pakfire_buildservice_parse_response(service, transfer, buffer, length, &response);
+       if (r) {
+               CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
+               goto ERROR;
+       }
+
 ERROR:
        if (transfer)
                pakfire_downloader_transfer_unref(transfer);
+       if (response)
+               json_object_put(response);
 
        return r;
 }
@@ -448,13 +554,10 @@ PAKFIRE_EXPORT int pakfire_buildservice_list_uploads(
        if (r)
                goto ERROR;
 
-       // XXX would be nice to have the JSON error here
-
        // Parse the response
-       response = pakfire_json_parse(service->ctx, buffer, length);
-       if (!response) {
-               CTX_ERROR(service->ctx, "Could not parse the response\n");
-               r = -EBADMSG;
+       r = pakfire_buildservice_parse_response(service, transfer, buffer, length, &response);
+       if (r) {
+               CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
                goto ERROR;
        }