From: Michael Tremer Date: Thu, 19 Oct 2023 20:33:10 +0000 (+0000) Subject: buildservice: Handle API errors correctly X-Git-Tag: 0.9.30~1439 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33de78f2bed9d493f4b3175eccc256145db5dbb8;p=pakfire.git buildservice: Handle API errors correctly Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/buildservice.c b/src/libpakfire/buildservice.c index f2643fa7e..bff778eee 100644 --- a/src/libpakfire/buildservice.c +++ b/src/libpakfire/buildservice.c @@ -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; }