From da6f361947c146713c6a15e08a42f9bbd51e95eb Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Thu, 19 Oct 2023 17:06:44 -0500 Subject: [PATCH] Refactor curl requests into helper functions Most curl requests now use a local curl handle that's created for that request, then destroyed afterwards. The dataset multi read/write still uses the global handle for now. --- src/rest_vol.c | 549 ++++++++++++++++--- src/rest_vol.h | 15 + src/rest_vol_attr.c | 1141 +++++---------------------------------- src/rest_vol_dataset.c | 140 +---- src/rest_vol_datatype.c | 68 +-- src/rest_vol_file.c | 255 +-------- src/rest_vol_group.c | 141 +---- src/rest_vol_link.c | 425 ++------------- src/rest_vol_object.c | 421 +++------------ 9 files changed, 844 insertions(+), 2311 deletions(-) diff --git a/src/rest_vol.c b/src/rest_vol.c index 99f3b8b4..d0ed8d34 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -39,7 +39,8 @@ */ hid_t H5_rest_id_g = H5I_UNINIT; -static hbool_t H5_rest_initialized_g = FALSE; +static hbool_t H5_rest_initialized_g = FALSE; +static hbool_t H5_rest_curl_initialized_g = FALSE; /* Identifiers for HDF5's error API */ hid_t H5_rest_err_stack_g = H5I_INVALID_HID; @@ -175,6 +176,9 @@ herr_t RV_get_index_of_matching_handle(dataset_transfer_info *transfer_info, siz /* Stub that throws an error when called */ void *RV_wrap_get_object(const void *obj); +/* Helper function that creates and sets some fields on a cURL handle. */ +CURL *RV_curl_setup_handle(server_info_t *server_info, char *err_buf); + /* The REST VOL connector's class structure. */ static const H5VL_class_t H5VL_rest_g = { HDF5_VOL_REST_VERSION, /* Connector struct version number */ @@ -400,9 +404,11 @@ H5_rest_init(hid_t vipl_id) #endif /* Initialize cURL */ - if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) + if (!H5_rest_curl_initialized_g && (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL))) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't initialize cURL"); + H5_rest_curl_initialized_g = true; + if (NULL == (curl = curl_easy_init())) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't initialize cURL easy handle"); @@ -869,6 +875,15 @@ H5_rest_set_connection_information(server_info_t *server_info) } } + /* TODO - Global curl handle is only used for dataset read/writes right now. + * Once that is removed, this will be unnecessary. */ + if (username && password) { + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, server_info->username)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, server_info->password)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); + } + done: if (config_file) fclose(config_file); @@ -1964,17 +1979,14 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t { RV_object_t *external_file = NULL; hbool_t is_relative_path = FALSE; - size_t host_header_len = 0; H5L_info2_t link_info; char *url_encoded_link_name = NULL; - char *host_header = NULL; char *path_dirname = NULL; char *tmp_link_val = NULL; char *url_encoded_path_name = NULL; const char *ext_filename = NULL; const char *ext_obj_path = NULL; - const char *base_URL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; long http_response; int url_len = 0; server_api_version version; @@ -1990,8 +2002,7 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (H5I_FILE != parent_obj->obj_type && H5I_GROUP != parent_obj->obj_type && H5I_DATATYPE != parent_obj->obj_type && H5I_DATASET != parent_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file, group, datatype or dataset"); - if ((base_URL = parent_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object does not have valid server URL"); + #ifdef RV_CONNECTOR_DEBUG printf("-> Finding object by path '%s' from parent object of type %s with URI %s\n\n", obj_path, object_type_to_string(parent_obj->obj_type), parent_obj->URI); @@ -2055,8 +2066,8 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (NULL == (url_encoded_path_name = H5_rest_url_encode_path(obj_path))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode object path"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, - "%s/?h5path=%s%s%s&follow_soft_links=1&follow_external_links=1", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, + "/?h5path=%s%s%s&follow_soft_links=1&follow_external_links=1", url_encoded_path_name, is_relative_path ? "&parent_id=" : "", is_relative_path ? parent_obj->URI : "")) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -2105,7 +2116,7 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (NULL == (url_encoded_link_name = curl_easy_escape(curl, H5_rest_basename(obj_path), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, pobj_URI, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", pobj_URI, url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); } @@ -2123,8 +2134,8 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t /* Handle the special case for the paths "." and "/" */ if (!strcmp(obj_path, ".") || !strcmp(obj_path, "/")) { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s", base_URL, - parent_obj_type_header, parent_obj->URI)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s", parent_obj_type_header, + parent_obj->URI)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); } else { @@ -2143,8 +2154,8 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t * [base_URL]/[object_type]/?h5path=[path_name] */ if ((url_len = snprintf( - request_url, URL_MAX_LENGTH, "%s/%s/%s?%s%s%sh5path=%s", base_URL, - parent_obj_type_header, (is_relative_path && is_group) ? parent_obj->URI : "", + request_endpoint, URL_MAX_LENGTH, "/%s/%s?%s%s%sh5path=%s", parent_obj_type_header, + (is_relative_path && is_group) ? parent_obj->URI : "", (is_relative_path && !is_group) ? "grpid=" : "", (is_relative_path && !is_group) ? parent_obj->URI : "", (is_relative_path && !is_group) ? "&" : "", url_encoded_path_name)) < 0) @@ -2156,51 +2167,18 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "Request URL size exceeded maximum URL size"); - /* Setup cURL for making GET requests */ - - /* Setup the host header */ - host_header_len = strlen(parent_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, parent_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_PATH, FAIL); + http_response = RV_curl_get(&parent_obj->domain->u.file.server_info, request_endpoint, + parent_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON); - if (CURLE_OK != curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get HTTP response code"); - - ret_value = HTTP_SUCCESS(http_response); + if (HTTP_SUCCESS(http_response)) + ret_value = TRUE; + else + HANDLE_RESPONSE(http_response, H5E_ATTR, H5E_CANTGET, FAIL); #ifdef RV_CONNECTOR_DEBUG printf("-> Object %s\n\n", ret_value ? "found" : "not found"); #endif - /* Clean up the cURL headers to prevent issues in potential recursive call */ - curl_slist_free_all(curl_headers); - curl_headers = NULL; - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(version, 0, 8, 0)) { if (0 > RV_parse_response(response_buffer.buffer, NULL, target_object_type, RV_parse_type)) @@ -2286,8 +2264,6 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t done: if (tmp_link_val) RV_free(tmp_link_val); - if (host_header) - RV_free(host_header); if (url_encoded_path_name) RV_free(url_encoded_path_name); if (url_encoded_link_name) @@ -2299,11 +2275,6 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (RV_file_close(external_file, H5P_DEFAULT, NULL) < 0) FUNC_DONE_ERROR(H5E_LINK, H5E_CANTCLOSEOBJ, FAIL, "can't close file referenced by external link"); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - return ret_value; } /* end RV_find_object_by_path */ @@ -2452,7 +2423,7 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo /* If retrieved domain is different than the domain through which this object * was accessed, replace the returned object's domain. */ if (is_external_domain) { - if (NULL == (new_domain = RV_malloc(sizeof(RV_object_t)))) + if (NULL == (new_domain = RV_calloc(sizeof(RV_object_t)))) FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_CANTALLOC, FAIL, "failed to allocate memory for new domain"); memcpy(new_domain, &found_domain, sizeof(RV_object_t)); @@ -2517,6 +2488,15 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo RV_free(GCPL_buf); GCPL_buf = NULL; loc_info_out->GCPL_base64 = NULL; + + if (new_domain) { + RV_free(new_domain->u.file.filepath_name); + RV_free(new_domain->u.file.server_info.username); + RV_free(new_domain->u.file.server_info.password); + RV_free(new_domain->u.file.server_info.base_URL); + RV_free(new_domain->handle_path); + RV_free(new_domain); + } } return ret_value; @@ -3808,3 +3788,448 @@ RV_wrap_get_object(const void *obj) done: return ret_value; } + +/* Helper function to perform a DELETE request to an endpoint on a server. + * Request endpoint must contain a leading slash. */ +long +RV_curl_delete(server_info_t *server_info, const char *request_endpoint, const char *filename) +{ + long ret_value = FAIL; + CURL *curl_local = NULL; + size_t host_header_len = 0; + + char curl_local_err_buf[CURL_ERROR_SIZE]; + char *host_header = NULL; + char request_url[URL_MAX_LENGTH]; + int url_len = 0; + struct curl_slist *curl_headers_local = NULL; + + /* Initial curl handle setup */ + if ((curl_local = RV_curl_setup_handle(server_info, curl_local_err_buf)) == NULL) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTCREATE, FAIL, "can't create curl handle"); + + /* Setup the host header */ + host_header_len = strlen(filename) + strlen(host_string) + 1; + + if (NULL == (host_header = (char *)RV_malloc(host_header_len))) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); + + strcpy(host_header, host_string); + + curl_headers_local = curl_slist_append( + curl_headers_local, strncat(host_header, filename, host_header_len - strlen(host_string) - 1)); + + /* Disable use of Expect: 100 Continue HTTP response */ + curl_headers_local = curl_slist_append(curl_headers_local, "Expect:"); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_HTTPHEADER, curl_headers_local)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", + curl_local_err_buf); + + /* Assemble request url */ + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s%s", server_info->base_URL, request_endpoint)) < + 0) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_SYSERRSTR, FAIL, + "H5Adelete(_by_name) request URL exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", + curl_local_err_buf); + + /* Make DELETE request */ + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_CUSTOMREQUEST, "DELETE")) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP DELETE request: %s", + curl_local_err_buf); +#ifdef RV_CONNECTOR_DEBUG + printf("-> Deleting object at URL: %s\n\n", request_url); + + printf(" /*************************************\\\n"); + printf("-> | Making DELETE request to the server |\n"); + printf(" \\*************************************/\n\n"); +#endif + + CURL_PERFORM_NO_ERR(curl_local, FAIL); + + if (CURLE_OK != curl_easy_getinfo(curl_local, CURLINFO_RESPONSE_CODE, &ret_value)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, ret_value, "can't get HTTP response code"); + +done: + if (host_header) + RV_free(host_header); + + if (curl_headers_local) { + curl_slist_free_all(curl_headers_local); + curl_headers_local = NULL; + } + + if (curl_local) { + curl_easy_cleanup(curl_local); + } + + return ret_value; +} + +/* Helper function to perform a PUT request to an endpoint on a server. + * Request endpoint must contain a leading slash. */ +long +RV_curl_put(server_info_t *server_info, const char *request_endpoint, const char *filename, + upload_info *uinfo, content_type_t content_type) +{ + long ret_value = FAIL; + CURL *curl_local = NULL; + size_t host_header_len = 0; + + char curl_local_err_buf[CURL_ERROR_SIZE]; + char *host_header = NULL; + char request_url[URL_MAX_LENGTH]; + int url_len = 0; + struct curl_slist *curl_headers_local = NULL; + + if ((curl_local = RV_curl_setup_handle(server_info, curl_local_err_buf)) == NULL) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTCREATE, FAIL, "can't create curl handle"); + + /* Setup the host header */ + host_header_len = strlen(filename) + strlen(host_string) + 1; + if (NULL == (host_header = (char *)RV_malloc(host_header_len))) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); + + strcpy(host_header, host_string); + + curl_headers_local = curl_slist_append( + curl_headers_local, strncat(host_header, filename, host_header_len - strlen(host_string) - 1)); + + /* Disable use of Expect: 100 Continue HTTP response */ + curl_headers_local = curl_slist_append(curl_headers_local, "Expect:"); + + /* Specify type of content being sent through cURL */ + switch (content_type) { + case CONTENT_TYPE_JSON: + curl_headers_local = curl_slist_append(curl_headers_local, "Content-Type: application/json"); + break; + case CONTENT_TYPE_OCTET_STREAM: + curl_headers_local = + curl_slist_append(curl_headers_local, "Content-Type: application/octet-stream"); + break; + case CONTENT_TYPE_UNINIT: + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "content type of transfer is unspecified"); + break; + } + + /* Assemble request url */ + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s%s", server_info->base_URL, request_endpoint)) < + 0) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_SYSERRSTR, FAIL, + "H5Adelete(_by_name) request URL exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_HTTPHEADER, curl_headers_local)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", + curl_local_err_buf); + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_UPLOAD, 1)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", + curl_local_err_buf); + if (uinfo) { + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_READDATA, uinfo)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL PUT data: %s", + curl_local_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl_local, CURLOPT_INFILESIZE_LARGE, (curl_off_t)uinfo->buffer_size)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL PUT data size: %s", + curl_local_err_buf); + } + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", + curl_local_err_buf); + +#ifdef RV_CONNECTOR_DEBUG + printf(" /**********************************\\\n"); + printf("-> | Making PUT request to the server |\n"); + printf(" \\**********************************/\n\n"); +#endif + + CURL_PERFORM_NO_ERR(curl_local, FAIL); + + if (CURLE_OK != curl_easy_getinfo(curl_local, CURLINFO_RESPONSE_CODE, &ret_value)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, ret_value, "can't get HTTP response code"); +done: + + if (host_header) + RV_free(host_header); + + if (curl_headers_local) { + curl_slist_free_all(curl_headers_local); + curl_headers_local = NULL; + } + + if (curl_local) + curl_easy_cleanup(curl_local); + + return ret_value; +} + +/* Helper function to perform a GET request to an endpoint on a server. + * Request endpoint must contain a leading slash. */ +long +RV_curl_get(server_info_t *server_info, const char *request_endpoint, const char *filename, + content_type_t content_type) +{ + herr_t ret_value = FAIL; + CURL *curl_local = NULL; + size_t host_header_len = 0; + + char curl_local_err_buf[CURL_ERROR_SIZE]; + char *host_header = NULL; + char request_url[URL_MAX_LENGTH]; + int url_len = 0; + struct curl_slist *curl_headers_local = NULL; + + if ((curl_local = RV_curl_setup_handle(server_info, curl_local_err_buf)) == NULL) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTCREATE, FAIL, "can't create curl handle"); + + /* Setup the host header */ + host_header_len = strlen(filename) + strlen(host_string) + 1; + if (NULL == (host_header = (char *)RV_malloc(host_header_len))) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); + + strcpy(host_header, host_string); + + curl_headers_local = curl_slist_append( + curl_headers_local, strncat(host_header, filename, host_header_len - strlen(host_string) - 1)); + + /* Specify type of content being sent through cURL */ + switch (content_type) { + case CONTENT_TYPE_JSON: + curl_headers_local = curl_slist_append(curl_headers_local, "Accept: application/json"); + break; + case CONTENT_TYPE_OCTET_STREAM: + curl_headers_local = curl_slist_append(curl_headers_local, "Accept: application/octet-stream"); + break; + case CONTENT_TYPE_UNINIT: + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "content type of transfer is unspecified"); + break; + } + + /* Disable use of Expect: 100 Continue HTTP response */ + curl_headers_local = curl_slist_append(curl_headers_local, "Expect:"); + + /* Assemble request url */ + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s%s", server_info->base_URL, request_endpoint)) < + 0) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_SYSERRSTR, FAIL, "cURL GET request URL exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_HTTPHEADER, curl_headers_local)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", + curl_local_err_buf); + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_HTTPGET, 1)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", + curl_local_err_buf); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", + curl_local_err_buf); + +#ifdef RV_CONNECTOR_DEBUG + printf(" /**********************************\\\n"); + printf("-> | Making GET request to the server |\n"); + printf(" \\**********************************/\n\n"); +#endif + + CURL_PERFORM_NO_ERR(curl_local, FAIL); + + if (CURLE_OK != curl_easy_getinfo(curl_local, CURLINFO_RESPONSE_CODE, &ret_value)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't get HTTP response code"); + +done: + if (host_header) + RV_free(host_header); + + if (curl_headers_local) { + curl_slist_free_all(curl_headers_local); + curl_headers_local = NULL; + } + + if (curl_local) + curl_easy_cleanup(curl_local); + + return ret_value; +} + +/* Helper function to perform a POST request to an endpoint on a server. + * Request endpoint must contain a leading slash. */ +long +RV_curl_post(server_info_t *server_info, const char *request_endpoint, const char *filename, + const char *post_data, size_t data_size, content_type_t content_type) +{ + herr_t ret_value = FAIL; + CURL *curl_local = NULL; + size_t host_header_len = 0; + + char curl_local_err_buf[CURL_ERROR_SIZE]; + char *host_header = NULL; + char request_url[URL_MAX_LENGTH]; + int url_len = 0; + struct curl_slist *curl_headers_local = NULL; + curl_off_t _data_size; + + if ((curl_local = RV_curl_setup_handle(server_info, curl_local_err_buf)) == NULL) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTCREATE, FAIL, "can't create curl handle"); + + /* Setup the host header */ + host_header_len = strlen(filename) + strlen(host_string) + 1; + if (NULL == (host_header = (char *)RV_malloc(host_header_len))) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); + + strcpy(host_header, host_string); + + curl_headers_local = curl_slist_append( + curl_headers_local, strncat(host_header, filename, host_header_len - strlen(host_string) - 1)); + + /* Specify type of content being sent through cURL */ + switch (content_type) { + case CONTENT_TYPE_JSON: + curl_headers_local = curl_slist_append(curl_headers_local, "Accept: application/json"); + break; + case CONTENT_TYPE_OCTET_STREAM: + curl_headers_local = curl_slist_append(curl_headers_local, "Accept: application/octet-stream"); + break; + case CONTENT_TYPE_UNINIT: + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "content type of transfer is unspecified"); + break; + } + + /* Disable use of Expect: 100 Continue HTTP response */ + curl_headers_local = curl_slist_append(curl_headers_local, "Expect:"); + + /* Assemble request url */ + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s%s", server_info->base_URL, request_endpoint)) < + 0) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_SYSERRSTR, FAIL, "cURL GET request URL exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_HTTPHEADER, curl_headers_local)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", + curl_local_err_buf); + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_POST, 1)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", + curl_local_err_buf); + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_POSTFIELDS, post_data)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL POST data: %s", curl_local_err_buf); + + /* Make sure that the size of the create request HTTP body can safely be cast to a curl_off_t */ + if (sizeof(curl_off_t) < sizeof(size_t)) + ASSIGN_TO_SMALLER_SIZE(_data_size, curl_off_t, data_size, size_t) + else if (sizeof(curl_off_t) > sizeof(size_t)) + _data_size = (curl_off_t)data_size; + else + ASSIGN_TO_SAME_SIZE_UNSIGNED_TO_SIGNED(_data_size, curl_off_t, data_size, size_t) + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_POSTFIELDSIZE_LARGE, _data_size)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL POST data size: %s", + curl_local_err_buf); + + if (CURLE_OK != curl_easy_setopt(curl_local, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", + curl_local_err_buf); + +#ifdef RV_CONNECTOR_DEBUG + printf(" /**********************************\\\n"); + printf("-> | Making POST request to the server |\n"); + printf(" \\**********************************/\n\n"); +#endif + + CURL_PERFORM_NO_ERR(curl_local, FAIL); + + if (CURLE_OK != curl_easy_getinfo(curl_local, CURLINFO_RESPONSE_CODE, &ret_value)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, ret_value, "can't get HTTP response code"); + +done: + if (host_header) + RV_free(host_header); + + if (curl_headers_local) { + curl_slist_free_all(curl_headers_local); + curl_headers_local = NULL; + } + + if (curl_local) + curl_easy_cleanup(curl_local); + + return ret_value; +} + +/* Helper function that creates and sets some fields on a cURL handle. */ +CURL * +RV_curl_setup_handle(server_info_t *server_info, char *err_buf) +{ + CURL *new_curl_handle = NULL; + curl_version_info_data *curl_ver = NULL; + char user_agent[128] = {'\0'}; + herr_t ret_value = SUCCEED; + + /* Initialize cURL */ + if (!H5_rest_curl_initialized_g && (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL))) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't initialize cURL"); + + H5_rest_curl_initialized_g = true; + + if (NULL == (new_curl_handle = curl_easy_init())) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't initialize cURL easy handle"); + + /* Instruct cURL to use the buffer for error messages */ + if (CURLE_OK != curl_easy_setopt(new_curl_handle, CURLOPT_ERRORBUFFER, err_buf)) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set cURL error buffer"); + + /* Allocate buffer for cURL to write responses to */ + /* TODO - For now this is still global. Have the local handles share the global buffer. */ + + /* + if (NULL == (response_buffer.buffer = (char *)RV_malloc(CURL_RESPONSE_BUFFER_DEFAULT_SIZE))) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate cURL response buffer"); + response_buffer.buffer_size = CURL_RESPONSE_BUFFER_DEFAULT_SIZE; + response_buffer.curr_buf_ptr = response_buffer.buffer; + */ + + /* Redirect cURL output to response buffer */ + if (CURLE_OK != + curl_easy_setopt(new_curl_handle, CURLOPT_WRITEFUNCTION, H5_rest_curl_write_data_callback)) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set cURL write function: %s", err_buf); + + /* Set cURL read function for UPLOAD operations */ + if (CURLE_OK != curl_easy_setopt(new_curl_handle, CURLOPT_READFUNCTION, H5_rest_curl_read_data_callback)) + FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set cURL read function: %s", err_buf); + + /* Set user agent string */ + curl_ver = curl_version_info(CURLVERSION_NOW); + if (snprintf(user_agent, sizeof(user_agent), "libhdf5/%d.%d.%d (%s; %s v%s)", H5_VERS_MAJOR, + H5_VERS_MINOR, H5_VERS_RELEASE, curl_ver->host, HDF5_VOL_REST_LIB_NAME, + HDF5_VOL_REST_LIB_VER) < 0) { + FUNC_GOTO_ERROR(H5E_VOL, H5E_SYSERRSTR, FAIL, "error creating user agent string"); + } + + if (CURLE_OK != curl_easy_setopt(new_curl_handle, CURLOPT_USERAGENT, user_agent)) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while setting CURL option (CURLOPT_USERAGENT)"); + + if (CURLE_OK != curl_easy_setopt(new_curl_handle, CURLOPT_USERNAME, server_info->username)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL username: %s", err_buf); + if (CURLE_OK != curl_easy_setopt(new_curl_handle, CURLOPT_PASSWORD, server_info->password)) + FUNC_GOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "can't set cURL password: %s", err_buf); + +done: + if (ret_value < 0) { + curl_easy_cleanup(new_curl_handle); + new_curl_handle = NULL; + } + + return new_curl_handle; +} diff --git a/src/rest_vol.h b/src/rest_vol.h index 913f8bd4..c214a8fb 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -570,6 +570,12 @@ typedef struct dataset_read_info { typedef enum transfer_type_t { UNINIT = 0, READ = 1, WRITE = 2 } transfer_type_t; +typedef enum content_type_t { + CONTENT_TYPE_UNINIT = 0, + CONTENT_TYPE_JSON = 1, + CONTENT_TYPE_OCTET_STREAM = 2 +} content_type_t; + typedef struct dataset_transfer_info { struct curl_slist *curl_headers; char *host_headers; @@ -725,6 +731,15 @@ herr_t RV_curl_multi_perform(CURL *curl_multi_ptr, dataset_transfer_info *transf hid_t file_space_id, void *buf, struct response_buffer resp_buffer)); +/* Helper functions for cURL requests to the server */ +long RV_curl_delete(server_info_t *server_info, const char *request_endpoint, const char *filename); +long RV_curl_put(server_info_t *server_info, const char *request_endpoint, const char *filename, + upload_info *uinfo, content_type_t content_type); +long RV_curl_get(server_info_t *server_info, const char *request_endpoint, const char *filename, + content_type_t content_type); +long RV_curl_post(server_info_t *server_info, const char *request_endpoint, const char *filename, + const char *post_data, size_t post_size, content_type_t content_type); + #define SERVER_VERSION_MATCHES_OR_EXCEEDS(version, major_needed, minor_needed, patch_needed) \ (version.major > major_needed) || (version.major == major_needed && version.minor > minor_needed) || \ (version.major == major_needed && version.minor == minor_needed && version.patch >= patch_needed) diff --git a/src/rest_vol_attr.c b/src/rest_vol_attr.c index 4d331b24..ea06a646 100644 --- a/src/rest_vol_attr.c +++ b/src/rest_vol_attr.c @@ -55,21 +55,20 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ RV_object_t *new_attribute = NULL; upload_info uinfo; size_t create_request_nalloc = 0; - size_t host_header_len = 0; size_t datatype_body_len = 0; size_t attr_name_len = 0; size_t path_size = 0; size_t path_len = 0; - char *host_header = NULL; char *create_request_body = NULL; char *datatype_body = NULL; char *shape_body = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; + const char *parent_obj_type_header = NULL; char *url_encoded_attr_name = NULL; int create_request_body_len = 0; int url_len = 0; - const char *base_URL = NULL; void *ret_value = NULL; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received attribute create call with following parameters:\n"); @@ -98,9 +97,6 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ H5I_DATASET != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file, group, datatype or dataset"); - if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); - /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "no write intent on file"); @@ -243,22 +239,6 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ printf("-> Attribute create request JSON:\n%s\n\n", create_request_body); #endif - /* Setup the host header */ - host_header_len = strlen(parent->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL that we are sending JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/json"); - /* URL-encode the attribute name to ensure that the resulting URL for the creation * operation contains no illegal characters */ @@ -271,93 +251,28 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ * or * "/datasets//attributes/", * depending on the type of the object the attribute is being attached to. */ - switch (new_attribute->u.attribute.parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s", base_URL, - new_attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, - "attribute create URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s", base_URL, - new_attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, - "attribute create URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s", base_URL, - new_attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, - "attribute create URL exceeded maximum URL size"); + if (RV_set_object_type_header(new_attribute->u.attribute.parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "parent object not a group, datatype or dataset"); - break; + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", parent_obj_type_header, + new_attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "attribute create URL exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> URL for attribute creation request: %s\n\n", request_url); + printf("-> URL for attribute creation request: %s\n\n", request_endpoint); #endif uinfo.buffer = create_request_body; uinfo.buffer_size = (size_t)create_request_body_len; uinfo.bytes_sent = 0; - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, new_attribute->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, new_attribute->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set up cURL to make HTTP PUT request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_READDATA, &uinfo)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL PUT data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)create_request_body_len)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL PUT data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Creating attribute\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making PUT request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTCREATE, NULL); + http_response = RV_curl_put(&new_attribute->domain->u.file.server_info, request_endpoint, + new_attribute->domain->u.file.filepath_name, &uinfo, CONTENT_TYPE_JSON); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, NULL, "can't create attribute"); #ifdef RV_CONNECTOR_DEBUG printf("-> Created attribute\n\n"); @@ -385,8 +300,6 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ RV_free(datatype_body); if (shape_body) RV_free(shape_body); - if (host_header) - RV_free(host_header); if (url_encoded_attr_name) curl_free(url_encoded_attr_name); @@ -395,15 +308,6 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ if (RV_attr_close(new_attribute, FAIL, NULL) < 0) FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute"); - /* Unset cURL UPLOAD option to ensure that future requests don't try to use PUT calls */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 0)) - FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't unset cURL PUT option: %s", curl_err_buf); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -430,15 +334,12 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na RV_object_t *parent = (RV_object_t *)obj; RV_object_t *attribute = NULL; size_t attr_name_len = 0; - size_t host_header_len = 0; size_t path_size = 0; size_t path_len = 0; - char *host_header = NULL; char *found_attr_name = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; char *url_encoded_attr_name = NULL; const char *parent_obj_type_header = NULL; - const char *base_URL = NULL; int url_len = 0; void *ret_value = NULL; @@ -472,9 +373,6 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na H5I_DATASET != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file, group, datatype or dataset"); - if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); - if (aapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid AAPL"); @@ -599,21 +497,6 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na "can't locate object that attribute is attached to"); } - /* Setup the host header */ - host_header_len = strlen(attribute->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, attribute->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* Redirect cURL from the base URL to * "/groups//attributes/", * "/datatypes//attributes/" @@ -625,7 +508,7 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "parent object not a group, datatype or dataset"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s?%s&include_attrs=1", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s?%s&include_attrs=1", parent_obj_type_header, attribute->u.attribute.parent_obj_URI, request_idx_type)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); @@ -634,41 +517,19 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "attribute open URL exceeded maximum URL size"); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, NULL); + if (RV_curl_get(&attribute->domain->u.file.server_info, request_endpoint, + attribute->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get attribute"); if (0 > RV_parse_response(response_buffer.buffer, (const void *)&loc_params->loc_data.loc_by_idx, &found_attr_name, RV_copy_attribute_name_by_index)) FUNC_GOTO_ERROR(H5E_ATTR, H5E_PARSEERROR, NULL, "failed to retrieve attribute names"); - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - if (url_encoded_attr_name) { curl_free(url_encoded_attr_name); url_encoded_attr_name = NULL; } - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - break; } /* H5VL_OBJECT_BY_IDX */ @@ -679,24 +540,9 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na /* Make a GET request to the server to retrieve information about the attribute */ - /* Setup the host header */ - host_header_len = strlen(attribute->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, attribute->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* URL-encode the attribute name to ensure that the resulting URL for the open * operation contains no illegal characters */ - const char *target_attr_name = found_attr_name ? (const char *)found_attr_name : attr_name; attr_name_len = strlen(target_attr_name); @@ -712,39 +558,20 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na if (RV_set_object_type_header(attribute->u.attribute.parent_obj_type, &parent_obj_type_header) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "parent object not a group, datatype or dataset"); - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s/attributes/%s", base_URL, parent_obj_type_header, - attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", parent_obj_type_header, + attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "attribute open URL exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> URL for attribute open request: %s\n\n", request_url); -#endif - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving attribute's info\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); + printf("-> URL for attribute open request: %s\n\n", request_endpoint); #endif - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, NULL); + if (RV_curl_get(&attribute->domain->u.file.server_info, request_endpoint, + attribute->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get attribute"); /* Set up a Dataspace for the opened Attribute */ if ((attribute->u.attribute.space_id = RV_parse_dataspace(response_buffer.buffer)) < 0) @@ -793,8 +620,6 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na } /* end if */ #endif - if (host_header) - RV_free(host_header); if (url_encoded_attr_name) curl_free(url_encoded_attr_name); @@ -806,11 +631,6 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na if (found_attr_name) RV_free(found_attr_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -835,13 +655,11 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) hbool_t is_transfer_binary = FALSE; htri_t is_variable_str; size_t dtype_size; - size_t host_header_len = 0; - char *host_header = NULL; char *url_encoded_attr_name = NULL; - char request_url[URL_MAX_LENGTH]; - const char *base_URL = NULL; - int url_len = 0; - herr_t ret_value = SUCCEED; + char request_endpoint[URL_MAX_LENGTH]; + const char *parent_obj_type_header = NULL; + int url_len = 0; + herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG printf("-> Received attribute read call with following parameters:\n"); @@ -856,9 +674,6 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) if (!buf) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "read buffer was NULL"); - if ((base_URL = attribute->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "attribute does not have valid server URL"); - /* Determine whether it's possible to receive the data as a binary blob instead of as JSON */ if (H5T_NO_CLASS == (dtype_class = H5Tget_class(dtype_id))) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "memory datatype is invalid"); @@ -879,23 +694,8 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) printf("-> Attribute's datatype size: %zu\n\n", dtype_size); #endif - /* Setup the host header */ - host_header_len = strlen(attribute->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, attribute->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* Instruct cURL on which type of transfer to perform, binary or JSON */ - curl_headers = curl_slist_append(curl_headers, is_transfer_binary ? "Accept: application/octet-stream" - : "Accept: application/json"); + content_type_t content_type = is_transfer_binary ? CONTENT_TYPE_OCTET_STREAM : CONTENT_TYPE_JSON; /* URL-encode the attribute name to ensure that the resulting URL for the read * operation contains no illegal characters @@ -909,85 +709,24 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) * or * "/datasets//attributes//value", * depending on the type of the object the attribute is attached to. */ - switch (attribute->u.attribute.parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s/value", base_URL, - attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute read URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s/value", - base_URL, attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < - 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute read URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s/value", - base_URL, attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < - 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute read URL exceeded maximum URL size"); - - break; - - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (RV_set_object_type_header(attribute->u.attribute.parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "parent object not a group, datatype or dataset"); -#ifdef RV_CONNECTOR_DEBUG - printf("-> URL for attribute read request: %s\n\n", request_url); -#endif + if ((url_len = + snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s/value", parent_obj_type_header, + attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute read URL exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> Reading attribute\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); + printf("-> URL for attribute read request: %s\n\n", request_endpoint); #endif - CURL_PERFORM(curl, H5E_ATTR, H5E_READERROR, FAIL); + if (RV_curl_get(&attribute->domain->u.file.server_info, request_endpoint, + attribute->domain->u.file.filepath_name, content_type) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't read from attribute"); memcpy(buf, response_buffer.buffer, (size_t)file_select_npoints * dtype_size); @@ -996,16 +735,9 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) printf("-> Attribute read response buffer:\n%s\n\n", response_buffer.buffer); #endif - if (host_header) - RV_free(host_header); if (url_encoded_attr_name) curl_free(url_encoded_attr_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -1032,12 +764,11 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * htri_t is_variable_str; size_t dtype_size; size_t write_body_len = 0; - size_t host_header_len = 0; - char *host_header = NULL; char *url_encoded_attr_name = NULL; - char request_url[URL_MAX_LENGTH]; - const char *base_URL = NULL; - int url_len = 0; + char request_endpoint[URL_MAX_LENGTH]; + const char *parent_obj_type_header = NULL; + int url_len = 0; + long http_response; herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG @@ -1053,9 +784,6 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * if (!buf) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "write buffer was NULL"); - if ((base_URL = attribute->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "attribute does not have valid server URL"); - /* Check for write access */ if (!(attribute->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file"); @@ -1080,23 +808,6 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * write_body_len = (size_t)file_select_npoints * dtype_size; - /* Setup the host header */ - host_header_len = strlen(attribute->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, attribute->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL on which type of transfer to perform, binary or JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/octet-stream"); - /* URL-encode the attribute name to ensure that the resulting URL for the write * operation contains no illegal characters */ @@ -1109,62 +820,19 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * * or * "/datasets//attributes//value", * depending on the type of the object the attribute is attached to. */ - switch (attribute->u.attribute.parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s/value", base_URL, - attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute write URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s/value", - base_URL, attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < - 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute write URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s/value", - base_URL, attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < - 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "attribute write URL exceeded maximum URL size"); + if (RV_set_object_type_header(attribute->u.attribute.parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "parent object not a group, datatype or dataset"); - break; + if ((url_len = + snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s/value", parent_obj_type_header, + attribute->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute write URL exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> URL for attribute write request: %s\n\n", request_url); + printf("-> URL for attribute write request: %s\n\n", request_endpoint); #endif /* Check to make sure that the size of the write body can safely be cast to a curl_off_t */ @@ -1179,52 +847,20 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * uinfo.buffer_size = write_body_len; uinfo.bytes_sent = 0; - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_READDATA, &uinfo)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL PUT data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, write_len)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL PUT data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Writing attribute\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making PUT request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif + http_response = RV_curl_put(&attribute->domain->u.file.server_info, request_endpoint, + attribute->domain->u.file.filepath_name, &uinfo, CONTENT_TYPE_OCTET_STREAM); - CURL_PERFORM(curl, H5E_ATTR, H5E_WRITEERROR, FAIL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't write to attribute"); done: #ifdef RV_CONNECTOR_DEBUG printf("-> Attribute write response buffer:\n%s\n\n", response_buffer.buffer); #endif - if (host_header) - RV_free(host_header); if (url_encoded_attr_name) curl_free(url_encoded_attr_name); - /* Unset cURL UPLOAD option to ensure that future requests don't try to use PUT calls */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 0)) - FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't unset cURL PUT option: %s", curl_err_buf); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -1244,16 +880,13 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * herr_t RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) { - RV_object_t *loc_obj = (RV_object_t *)obj; - size_t host_header_len = 0; - char *host_header = NULL; - char request_url[URL_MAX_LENGTH]; + RV_object_t *loc_obj = (RV_object_t *)obj; + char request_endpoint[URL_MAX_LENGTH]; char *url_encoded_attr_name = NULL; char *found_attr_name = NULL; int url_len = 0; const char *parent_obj_type_header = NULL; const char *request_idx_type = NULL; - const char *base_URL = NULL; herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG @@ -1266,9 +899,6 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not an attribute, file, group, datatype or dataset"); - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - switch (args->op_type) { /* H5Aget_create_plist */ case H5VL_ATTR_GET_ACPL: { @@ -1302,61 +932,19 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) (url_encoded_attr_name = curl_easy_escape(curl, loc_obj->u.attribute.attr_name, 0))) FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't URL-encode attribute name"); - switch (loc_obj->u.attribute.parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s", - base_URL, loc_obj->u.attribute.parent_obj_URI, - url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info request URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf( - request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s", base_URL, - loc_obj->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info request URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf( - request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s", base_URL, - loc_obj->u.attribute.parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info request URL exceeded maximum URL size"); - - break; + if (RV_set_object_type_header(loc_obj->u.attribute.parent_obj_type, + &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, + "can't get path header from parent object type"); - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", + parent_obj_type_header, loc_obj->u.attribute.parent_obj_URI, + url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, + "H5Aget_info request URL exceeded maximum URL size"); break; } /* H5VL_OBJECT_BY_SELF */ @@ -1399,59 +987,18 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) if (NULL == (url_encoded_attr_name = curl_easy_escape(curl, attr_name, 0))) FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't URL-encode attribute name"); - switch (parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s", - base_URL, parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info_by_name request URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s", - base_URL, parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info_by_name request URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s", - base_URL, parent_obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aget_info_by_name request URL exceeded maximum URL size"); + if (RV_set_object_type_header(parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, + "can't get path header from parent object type"); - break; + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", + parent_obj_type_header, parent_obj_URI, url_encoded_attr_name)) < + 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, + "H5Aget_info_by_name request URL exceeded maximum URL size"); break; } /* H5VL_OBJECT_BY_NAME */ @@ -1499,21 +1046,6 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ATTR, H5E_PATH, FAIL, "can't locate object that attribute is attached to"); - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append( - curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* Redirect cURL from the base URL to * "/groups//attributes/", * "/datatypes//attributes/" @@ -1524,57 +1056,31 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get path header from parent object type"); - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s?%s&include_attrs=1", base_URL, - parent_obj_type_header, parent_obj_URI, request_idx_type)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s?%s&include_attrs=1", + parent_obj_type_header, parent_obj_URI, request_idx_type)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, - loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, - loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, FAIL); + + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute"); if (0 > RV_parse_response(response_buffer.buffer, &loc_params->loc_data.loc_by_idx, &found_attr_name, RV_copy_attribute_name_by_index)) FUNC_GOTO_ERROR(H5E_ATTR, H5E_PARSEERROR, FAIL, "failed to retrieve attribute names"); - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - if (url_encoded_attr_name) { curl_free(url_encoded_attr_name); url_encoded_attr_name = NULL; } - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - if (NULL == (url_encoded_attr_name = curl_easy_escape(curl, found_attr_name, 0))) FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't URL-encode attribute name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s/attributes/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", parent_obj_type_header, parent_obj_URI, url_encoded_attr_name)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1588,45 +1094,9 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) } /* end switch */ /* Make a GET request to the server to retrieve the attribute's info */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving attribute info at URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute"); /* Retrieve the attribute's info */ if (RV_parse_response(response_buffer.buffer, NULL, attr_info, RV_get_attr_info_callback) < 0) @@ -1707,21 +1177,6 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) break; } - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append( - curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* Redirect cURL from the base URL to * "/groups//attributes/", * "/datatypes//attributes/" @@ -1732,34 +1187,17 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "parent object not a group, datatype or dataset"); - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s?%s&include_attrs=1", base_URL, - parent_obj_type_header, parent_obj_URI, request_idx_type)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s?%s&include_attrs=1", + parent_obj_type_header, parent_obj_URI, request_idx_type)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, - loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, - loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute"); if (0 > RV_parse_response(response_buffer.buffer, &loc_params->loc_data.loc_by_idx, &found_attr_name, RV_copy_attribute_name_by_index)) @@ -1772,21 +1210,11 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) name_buf[name_buf_size - 1] = '\0'; } /* end if */ - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - if (url_encoded_attr_name) { curl_free(url_encoded_attr_name); url_encoded_attr_name = NULL; } - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - break; } /* H5VL_OBJECT_BY_IDX */ @@ -1829,16 +1257,9 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) } /* end switch */ done: - if (host_header) - RV_free(host_header); if (url_encoded_attr_name) curl_free(url_encoded_attr_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } - if (found_attr_name) { RV_free(found_attr_name); found_attr_name = NULL; @@ -1867,21 +1288,19 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci RV_object_t *loc_obj = (RV_object_t *)obj; RV_object_t *attr_iter_obj_typed = NULL; H5I_type_t parent_obj_type = H5I_UNINIT; - size_t host_header_len = 0; H5VL_attr_get_args_t attr_get_args; size_t attr_name_to_delete_len = 0; hid_t attr_iter_object_id = H5I_INVALID_HID; void *attr_iter_object = NULL; - char *host_header = NULL; char *obj_URI; char temp_URI[URI_MAX_LENGTH]; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; char attr_name_to_delete[ATTRIBUTE_NAME_MAX_LENGTH]; char *url_encoded_attr_name = NULL; const char *parent_obj_type_header = NULL; - const char *base_URL = NULL; int url_len = 0; herr_t ret_value = SUCCEED; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received attribute-specific call with following parameters:\n"); @@ -1892,9 +1311,6 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci H5I_DATATYPE != loc_obj->obj_type && H5I_DATASET != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file, group, datatype or dataset"); - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - switch (args->op_type) { /* H5Adelete (_by_name/_by_idx) */ case H5VL_ATTR_DELETE_BY_IDX: { @@ -1940,7 +1356,7 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "parent object not a group, datatype or dataset"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s/attributes/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", parent_obj_type_header, temp_URI, url_encoded_attr_name)) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1948,44 +1364,13 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "H5Adelete(_by_name) request URL exceeded maximum URL size"); - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP DELETE request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + http_response = + RV_curl_delete(&loc_obj->domain->u.file.server_info, (const char *)request_endpoint, + (const char *)loc_obj->domain->u.file.filepath_name); -#ifdef RV_CONNECTOR_DEBUG - printf("-> Deleting attribute at URL: %s\n\n", request_url); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "can't delete attribute"); - printf(" /*************************************\\\n"); - printf("-> | Making DELETE request to the server |\n"); - printf(" \\*************************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTREMOVE, FAIL); break; } @@ -2073,95 +1458,24 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci * or * "/datasets//attributes/, * depending on the type of the object the attribute is attached to. */ - switch (parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Adelete(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Adelete(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Adelete(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (RV_set_object_type_header(parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, + "parent object not a group, datatype or dataset"); - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP DELETE request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", + parent_obj_type_header, obj_URI, url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); -#ifdef RV_CONNECTOR_DEBUG - printf("-> Deleting attribute at URL: %s\n\n", request_url); + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, + "H5Adelete(_by_name) request URL exceeded maximum URL size"); - printf(" /*************************************\\\n"); - printf("-> | Making DELETE request to the server |\n"); - printf(" \\*************************************/\n\n"); -#endif + http_response = + RV_curl_delete(&loc_obj->domain->u.file.server_info, (const char *)request_endpoint, + (const char *)loc_obj->domain->u.file.filepath_name); - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTREMOVE, FAIL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "can't delete attribute"); break; } /* H5VL_ATTR_DELETE */ @@ -2170,7 +1484,6 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci case H5VL_ATTR_EXISTS: { const char *attr_name = args->args.exists.name; hbool_t *ret = args->args.exists.exists; - long http_response; switch (loc_params->type) { /* H5Aexists */ @@ -2239,99 +1552,20 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci * or * "/datasets//attributes/, * depending on the type of the object the attribute is attached to. */ - switch (parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aexists(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aexists(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes/%s", - base_URL, obj_URI, url_encoded_attr_name)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aexists(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Attribute existence check at URL: %s\n\n", request_url); + if (RV_set_object_type_header(parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, + "parent object not a group, datatype or dataset"); - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes/%s", + parent_obj_type_header, obj_URI, url_encoded_attr_name)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - CURL_PERFORM_NO_ERR(curl, FAIL); + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, + "H5Aexists(_by_name) request URL exceeded maximum URL size"); - if (CURLE_OK != curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get HTTP response code"); + http_response = RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON); if (HTTP_SUCCESS(http_response)) *ret = TRUE; @@ -2647,57 +1881,17 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci * or * "/datasets//attributes", * depending on the type of the object the attribute is attached to. */ - switch (parent_obj_type) { - case H5I_FILE: - case H5I_GROUP: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/attributes", base_URL, - obj_URI)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aiterate(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATATYPE: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s/attributes", - base_URL, obj_URI)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aiterate(_by_name) request URL exceeded maximum URL size"); - - break; - - case H5I_DATASET: - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/attributes", - base_URL, obj_URI)) < 0) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, - "H5Aiterate(_by_name) request URL exceeded maximum URL size"); + if (RV_set_object_type_header(parent_obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, + "parent object not a group, datatype or dataset"); - break; + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/attributes", + parent_obj_type_header, obj_URI)) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "snprintf error"); - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, - "parent object not a file, group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, + "H5Aiterate(_by_name) request URL exceeded maximum URL size"); /* Register an hid_t for the attribute's parent object */ @@ -2734,44 +1928,9 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci /* Make a GET request to the server to retrieve all of the attributes attached to the given object */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all attributes attached to object using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_ATTR, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute"); if (RV_parse_response(response_buffer.buffer, &attr_iter_data, NULL, RV_attr_iter_callback) < 0) FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't iterate over attributes"); @@ -2790,9 +1949,6 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci } /* end switch */ done: - if (host_header) - RV_free(host_header); - if (attr_iter_object_id >= 0) { if (H5I_FILE == parent_obj_type) { if (H5Fclose(attr_iter_object_id) < 0) @@ -2818,20 +1974,9 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "invalid attribute parent object type"); } /* end if */ - /* In case a custom DELETE request was made, reset the request to NULL - * to prevent any possible future issues with requests - */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL)) - FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't reset cURL custom request: %s", curl_err_buf); - if (url_encoded_attr_name) curl_free(url_encoded_attr_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index bf46173e..ee0a651b 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -129,15 +129,13 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na { RV_object_t *parent = (RV_object_t *)obj; RV_object_t *new_dataset = NULL; - curl_off_t create_request_body_len = 0; - size_t host_header_len = 0; + size_t create_request_body_len = 0; size_t path_size = 0; size_t path_len = 0; - char *host_header = NULL; char *create_request_body = NULL; - char request_url[URL_MAX_LENGTH]; - const char *base_URL = NULL; - int url_len = 0; + char request_endpoint[URL_MAX_LENGTH]; + int url_len = 0; + long http_response; void *ret_value = NULL; #ifdef RV_CONNECTOR_DEBUG @@ -154,8 +152,6 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na if (H5I_FILE != parent->obj_type && H5I_GROUP != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file or group"); - if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) @@ -204,42 +200,13 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na new_dataset->u.dataset.dcpl_id = H5P_DATASET_CREATE_DEFAULT; /* Form the request body to give the new Dataset its properties */ - { - size_t tmp_len = 0; - - if (RV_setup_dataset_create_request_body(obj, name, type_id, space_id, lcpl_id, dcpl_id, - &create_request_body, &tmp_len) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, - "can't convert dataset creation parameters to JSON"); - - /* Check to make sure that the size of the create request HTTP body can safely be cast to a curl_off_t - */ - if (sizeof(curl_off_t) < sizeof(size_t)) - ASSIGN_TO_SMALLER_SIZE(create_request_body_len, curl_off_t, tmp_len, size_t) - else if (sizeof(curl_off_t) > sizeof(size_t)) - create_request_body_len = (curl_off_t)tmp_len; - else - ASSIGN_TO_SAME_SIZE_UNSIGNED_TO_SIGNED(create_request_body_len, curl_off_t, tmp_len, size_t) - } - - /* Setup the host header */ - host_header_len = strlen(parent->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL that we are sending JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/json"); + if (RV_setup_dataset_create_request_body(obj, name, type_id, space_id, lcpl_id, dcpl_id, + &create_request_body, &create_request_body_len) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, + "can't convert dataset creation parameters to JSON"); /* Redirect cURL from the base URL to "/datasets" to create the dataset */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets", base_URL)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/datasets")) < 0) FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, NULL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -250,33 +217,13 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na printf("-> Dataset creation request URL: %s\n\n", request_url); #endif - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, new_dataset->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, new_dataset->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set up cURL to make HTTP POST request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POSTFIELDS, create_request_body)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL POST data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, create_request_body_len)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL POST data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); + http_response = RV_curl_post(&new_dataset->domain->u.file.server_info, request_endpoint, + new_dataset->domain->u.file.filepath_name, (const char *)create_request_body, + create_request_body_len, CONTENT_TYPE_JSON); -#ifdef RV_CONNECTOR_DEBUG - printf("-> Creating dataset\n\n"); - - printf(" /***********************************\\\n"); - printf("-> | Making POST request to the server |\n"); - printf(" \\***********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_DATASET, H5E_CANTCREATE, NULL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, NULL, "can't create dataset, response HTTP %ld", + http_response); #ifdef RV_CONNECTOR_DEBUG printf("-> Created dataset\n\n"); @@ -307,19 +254,11 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na if (create_request_body) RV_free(create_request_body); - if (host_header) - RV_free(host_header); - /* Clean up allocated dataset object if there was an issue */ if (new_dataset && !ret_value) if (RV_dataset_close(new_dataset, FAIL, NULL) < 0) FUNC_DONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, "can't close dataset"); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -1245,7 +1184,7 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r H5VL_file_specific_args_t vol_flush_args; size_t host_header_len = 0; char *host_header = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; const char *base_URL = NULL; #ifdef RV_CONNECTOR_DEBUG @@ -1258,8 +1197,6 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r if (H5I_DATASET != dset->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a dataset"); - if ((base_URL = dset->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataset does not have valid server URL"); switch (args->op_type) { /* H5Dget_access_plist */ @@ -1313,41 +1250,11 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "can't flush datase's domain"); /* Make GET request to dataset with 'verbose' parameter for HSDS. */ - snprintf(request_url, URL_MAX_LENGTH, "%s%s%s%s", base_URL, "/datasets/", dset->URI, - "?verbose=1"); + snprintf(request_endpoint, URL_MAX_LENGTH, "%s%s%s", "/datasets/", dset->URI, "?verbose=1"); - /* Setup the host header */ - host_header_len = strlen(dset->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, dset->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, dset->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, dset->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - CURL_PERFORM(curl, H5E_DATASET, H5E_CANTGET, FAIL); + if (RV_curl_get(&dset->domain->u.file.server_info, request_endpoint, + dset->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset"); if (RV_parse_allocated_size_callback(response_buffer.buffer, NULL, args->args.get_storage_size.storage_size) < 0) @@ -1372,13 +1279,6 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r } /* end switch */ done: - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } - - RV_free(host_header); - PRINT_ERROR_STACK; return ret_value; diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index 37a18721..00006d9a 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -70,21 +70,19 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n RV_object_t *new_datatype = NULL; size_t commit_request_nalloc = 0; size_t link_body_nalloc = 0; - size_t host_header_len = 0; size_t datatype_body_len = 0; size_t path_size = 0; size_t path_len = 0; - const char *base_URL = NULL; - char *host_header = NULL; char *commit_request_body = NULL; char *datatype_body = NULL; char *link_body = NULL; char *path_dirname = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; int commit_request_len = 0; int link_body_len = 0; int url_len = 0; void *ret_value = NULL; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received datatype commit call with following parameters:\n"); @@ -103,9 +101,6 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n if (H5I_FILE != parent->obj_type && H5I_GROUP != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file or group"); - if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); - /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "no write intent on file"); @@ -230,24 +225,8 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n printf("-> Datatype commit request body:\n%s\n\n", commit_request_body); #endif - /* Setup the host header */ - host_header_len = strlen(parent->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL that we are sending JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/json"); - /* Redirect cURL from the base URL to "/datatypes" to commit the datatype */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes", base_URL)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/datatypes")) < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_SYSERRSTR, NULL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -255,36 +234,16 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n "datatype create URL size exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> Datatype commit URL: %s\n\n", request_url); + printf("-> Datatype commit URL: %s\n\n", request_endpoint); #endif - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, new_datatype->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, new_datatype->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set up cURL to make HTTP POST request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POSTFIELDS, commit_request_body)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL POST data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)commit_request_len)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL POST data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); + http_response = RV_curl_post(&parent->domain->u.file.server_info, request_endpoint, + parent->domain->u.file.filepath_name, (const char *)commit_request_body, + (size_t)commit_request_len, CONTENT_TYPE_JSON); -#ifdef RV_CONNECTOR_DEBUG - printf("-> Committing datatype\n\n"); - - printf(" /***********************************\\\n"); - printf("-> | Making POST request to the server |\n"); - printf(" \\***********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_DATATYPE, H5E_BADVALUE, NULL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "couldn't commit datatype: received HTTP %ld", + http_response); #ifdef RV_CONNECTOR_DEBUG printf("-> Committed datatype\n\n"); @@ -312,8 +271,6 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n RV_free(path_dirname); if (commit_request_body) RV_free(commit_request_body); - if (host_header) - RV_free(host_header); if (datatype_body) RV_free(datatype_body); if (link_body) @@ -324,11 +281,6 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n if (RV_datatype_close(new_datatype, FAIL, NULL) < 0) FUNC_DONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close datatype"); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; diff --git a/src/rest_vol_file.c b/src/rest_vol_file.c index 53c251f6..24c74267 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -44,17 +44,17 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h { RV_object_t *new_file = NULL; size_t name_length; - size_t host_header_len = 0; size_t base64_buf_size = 0; size_t plist_nalloc = 0; size_t create_request_nalloc = 0; int create_request_body_len = 0; - char *host_header = NULL; char *base64_plist_buffer = NULL; const char *fmt_string = NULL; char *create_request_body = NULL; void *ret_value = NULL; void *binary_plist_buffer = NULL; + const char *request_endpoint = NULL; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received file create call with following parameters:\n"); @@ -125,76 +125,23 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h strncpy(new_file->u.file.filepath_name, name, name_length); new_file->u.file.filepath_name[name_length] = '\0'; - /* Setup the host header */ - host_header_len = name_length + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, name, name_length)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, new_file->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, new_file->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, new_file->u.file.server_info.base_URL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - /* Before making the actual request, check the file creation flags for * the use of H5F_ACC_TRUNC. In this case, we want to check with the * server before trying to create a file which already exists. */ if (flags & H5F_ACC_TRUNC) { - long http_response; - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); -#ifdef RV_CONNECTOR_DEBUG - printf("-> H5F_ACC_TRUNC specified; checking if file exists\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - /* Note that we use the special version of CURL_PERFORM because if - * the file doesn't exist, and the check for this throws a 404 response, - * the standard CURL_PERFORM would fail this entire function. We don't - * want this, we just want to get an idea of whether the file exists - * or not. - */ - CURL_PERFORM_NO_ERR(curl, NULL); - - if (CURLE_OK != curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get HTTP response code"); + /* Don't fail function if this file doesn't exist */ + http_response = RV_curl_get(&new_file->u.file.server_info, "/", new_file->u.file.filepath_name, + CONTENT_TYPE_JSON); /* If the file exists, go ahead and delete it before proceeding */ if (HTTP_SUCCESS(http_response)) { - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, - "can't set up cURL to make HTTP DELETE request: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> File existed and H5F_ACC_TRUNC specified; deleting file\n\n"); - - printf(" /*************************************\\\n"); - printf("-> | Making DELETE request to the server |\n"); - printf(" \\*************************************/\n\n"); -#endif + http_response = RV_curl_delete(&new_file->u.file.server_info, "/", + (const char *)new_file->u.file.filepath_name); - CURL_PERFORM(curl, H5E_FILE, H5E_CANTREMOVE, NULL); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't reset cURL custom request: %s", - curl_err_buf); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTREMOVE, NULL, "can't delete existing file"); } /* end if */ } /* end if */ @@ -234,22 +181,11 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h uinfo.buffer_size = (size_t)create_request_body_len; uinfo.bytes_sent = 0; - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set up cURL to make HTTP PUT request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_READDATA, &uinfo)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL PUT data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)create_request_body_len)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL PUT data size: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Creating file\n\n"); + http_response = RV_curl_put(&new_file->u.file.server_info, "/", new_file->u.file.filepath_name, &uinfo, + CONTENT_TYPE_JSON); - printf(" /**********************************\\\n"); - printf("-> | Making PUT request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - CURL_PERFORM(curl, H5E_FILE, H5E_CANTCREATE, NULL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, "can't create file"); #ifdef RV_CONNECTOR_DEBUG printf("-> Created file\n\n"); @@ -278,9 +214,6 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h } /* end if */ #endif - if (host_header) - RV_free(host_header); - RV_free(base64_plist_buffer); RV_free(binary_plist_buffer); RV_free(create_request_body); @@ -290,19 +223,6 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h if (RV_file_close(new_file, FAIL, NULL) < 0) FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, NULL, "can't close file"); - /* Reset cURL custom request to prevent issues with future requests */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL)) - FUNC_DONE_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't reset cURL custom request: %s", curl_err_buf); - - /* Unset cURL UPLOAD option to ensure that future requests don't try to use PUT calls */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 0)) - FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't unset cURL PUT option: %s", curl_err_buf); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -326,9 +246,8 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi { RV_object_t *file = NULL; size_t name_length; - size_t host_header_len = 0; - char *host_header = NULL; - void *ret_value = NULL; + void *ret_value = NULL; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received file open call with following parameters:\n"); @@ -374,39 +293,11 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi strncpy(file->u.file.filepath_name, name, name_length); file->u.file.filepath_name[name_length] = '\0'; - /* Setup the host header */ - host_header_len = name_length + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, name, name_length)); + http_response = + RV_curl_get(&file->u.file.server_info, "/", file->u.file.filepath_name, CONTENT_TYPE_JSON); - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, file->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, file->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, file->u.file.server_info.base_URL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving info for file open\n\n"); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_FILE, H5E_CANTOPENFILE, NULL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't get file"); /* Store the opened file's URI */ if (RV_parse_response(response_buffer.buffer, NULL, file->URI, RV_copy_object_URI_callback) < 0) @@ -446,19 +337,11 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi } #endif - if (host_header) - RV_free(host_header); - /* Clean up allocated file object if there was an issue */ if (file && !ret_value) if (RV_file_close(file, FAIL, NULL) < 0) FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, NULL, "can't close file"); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -626,12 +509,10 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void { RV_object_t *file = (RV_object_t *)obj; herr_t ret_value = SUCCEED; - size_t host_header_len; size_t name_length; long http_response; - char *host_header = NULL; - const char *filename = NULL; - char *request_url = NULL; + const char *filename = NULL; + char request_endpoint[URL_MAX_LENGTH]; server_info_t *server_info = NULL; #ifdef RV_CONNECTOR_DEBUG @@ -658,50 +539,12 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void name_length = strlen(filename); - /* Setup the host header */ - host_header_len = name_length + strlen(host_string) + 1; - - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, filename, name_length)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (NULL == (request_url = (char *)RV_malloc( - strlen(flush_string) + strlen(target_domain->u.file.server_info.base_URL) + 1))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for request URL"); - - snprintf(request_url, URL_MAX_LENGTH, "%s%s", target_domain->u.file.server_info.base_URL, - flush_string); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, file->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, file->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + snprintf(request_endpoint, URL_MAX_LENGTH, "%s", flush_string); /* Server only checks for flush parameter on PUT operations */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL to make HTTP PUTrequest: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)0)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL upload size: %s", curl_err_buf); - - CURL_PERFORM_NO_ERR(curl, FAIL); - if (CURLE_OK != curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get HTTP response code from cURL: %s", - curl_err_buf); - - if (http_response != HTTP_NO_CONTENT) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "invalid server response from flush"); + if (HTTP_NO_CONTENT != RV_curl_put(&file->u.file.server_info, request_endpoint, + file->u.file.filepath_name, NULL, CONTENT_TYPE_JSON)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unexpected return from flush"); break; @@ -748,20 +591,6 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void name_length = strlen(filename); - /* Setup the host header */ - host_header_len = name_length + strlen(host_string) + 1; - - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, filename, name_length)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* H5Fdelete doesn't receive a file handle, so the username/password must be pulled * from environment for now */ if ((server_info = RV_calloc(sizeof(server_info_t))) == NULL) @@ -770,21 +599,10 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void if (H5_rest_set_connection_information(server_info) < 0) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get server connection information"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, server_info->username)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, server_info->password)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, server_info->base_URL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + http_response = RV_curl_delete(server_info, "/", filename); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP DELETE request: %s", curl_err_buf); - - CURL_PERFORM(curl, H5E_FILE, H5E_CLOSEERROR, FAIL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't delete file"); break; } /* H5VL_FILE_DELETE */ @@ -800,23 +618,6 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void done: PRINT_ERROR_STACK; - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - - /* Restore CUSTOMREQUEST to internal default */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP DELETE request: %s", - curl_err_buf); - - if (host_header) { - RV_free(host_header); - } - - if (request_url) - RV_free(request_url); - if (server_info) { RV_free(server_info->base_URL); RV_free(server_info->username); diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index 8f795170..be8bef22 100644 --- a/src/rest_vol_group.c +++ b/src/rest_vol_group.c @@ -44,22 +44,20 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name RV_object_t *parent = (RV_object_t *)obj; RV_object_t *new_group = NULL; size_t create_request_nalloc = 0; - size_t host_header_len = 0; size_t base64_buf_size = 0; size_t plist_nalloc = 0; size_t path_size = 0; size_t path_len = 0; - const char *base_URL = NULL; - char *host_header = NULL; char *create_request_body = NULL; char *path_dirname = NULL; char *base64_plist_buffer = NULL; char target_URI[URI_MAX_LENGTH]; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; int create_request_body_len = 0; int url_len = 0; void *binary_plist_buffer = NULL; void *ret_value = NULL; + long http_response; #ifdef RV_CONNECTOR_DEBUG printf("-> Received group create call with following parameters:\n"); @@ -76,9 +74,6 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name if (H5I_FILE != parent->obj_type && H5I_GROUP != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file or group"); - if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); - if (gapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid GAPL"); @@ -163,6 +158,7 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name if (H5Pget_create_intermediate_group(lcpl_id, &crt_intmd_group)) FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get flag value in lcpl"); + /* If group in provided path doesn't exist, create it */ if (crt_intmd_group) { /* Remove trailing slash to avoid infinite loop due to H5_dirname */ if (path_dirname[strlen(path_dirname) - 1] == '/') @@ -177,7 +173,12 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name search_ret = RV_find_object_by_path(parent, path_dirname, &obj_type, RV_copy_object_URI_callback, NULL, target_URI); - RV_group_close(intmd_group, H5P_DEFAULT, NULL); + if (!search_ret || search_ret < 0) + FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, NULL, "couldn't get URI of intermediate group"); + + if (RV_group_close(intmd_group, H5P_DEFAULT, NULL) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, NULL, + "can't close intermediate group"); } else FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, NULL, "can't locate target for group link"); @@ -229,59 +230,25 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name #endif } /* end if */ - /* Setup the host header */ - host_header_len = strlen(parent->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, strncat(host_header, parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL that we are sending JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/json"); - /* Redirect cURL from the base URL to "/groups" to create the group */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups", base_URL)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups")) < 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_SYSERRSTR, NULL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_SYM, H5E_SYSERRSTR, NULL, "group create URL size exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> Group create request URL: %s\n\n", request_url); + printf("-> Group create request URL: %s\n\n", request_endpoint); #endif - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, new_group->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, new_group->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set up cURL to make HTTP POST request: %s", - curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, create_request_body ? create_request_body : "")) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL POST data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)create_request_body_len)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL POST data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Creating group\n\n"); - - printf(" /***********************************\\\n"); - printf("-> | Making POST request to the server |\n"); - printf(" \\***********************************/\n\n"); -#endif + http_response = RV_curl_post(&new_group->domain->u.file.server_info, request_endpoint, + parent->domain->u.file.filepath_name, + create_request_body ? (const char *)create_request_body : "", + (size_t)create_request_body_len, CONTENT_TYPE_JSON); - CURL_PERFORM(curl, H5E_SYM, H5E_CANTCREATE, NULL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTCREATE, NULL, "can't create group: received HTTP %ld", + http_response); #ifdef RV_CONNECTOR_DEBUG printf("-> Created group\n\n"); @@ -309,8 +276,6 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name RV_free(path_dirname); if (create_request_body) RV_free(create_request_body); - if (host_header) - RV_free(host_header); /* Clean up allocated group object if there was an issue */ if (new_group && !ret_value) @@ -322,11 +287,6 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name if (binary_plist_buffer) RV_free(binary_plist_buffer); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -485,12 +445,9 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, herr_t RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) { - RV_object_t *loc_obj = (RV_object_t *)obj; - size_t host_header_len = 0; - char *host_header = NULL; - char request_url[URL_MAX_LENGTH]; + RV_object_t *loc_obj = (RV_object_t *)obj; + char request_endpoint[URL_MAX_LENGTH]; int url_len = 0; - const char *base_URL = NULL; herr_t ret_value = SUCCEED; loc_info loc_info_out; @@ -503,8 +460,6 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) if (H5I_FILE != loc_obj->obj_type && H5I_GROUP != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a group"); - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object does not have valid server URL"); switch (args->op_type) { /* H5Gget_create_plist */ @@ -532,8 +487,8 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) #endif /* Redirect cURL from the base URL to "/groups/" to get information about the group */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s", base_URL, - loc_obj->URI)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s", loc_obj->URI)) < + 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -581,8 +536,7 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) #endif /* Redirect cURL from the base URL to "/groups/" to get information about the group */ - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s", base_URL, temp_URI)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s", temp_URI)) < 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -608,44 +562,9 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "invalid loc_params type"); } /* end switch */ - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving group info at URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - /* Make request to server to retrieve the group info */ - CURL_PERFORM(curl, H5E_SYM, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group"); /* Parse response from server and retrieve the relevant group information * (currently, just the number of links in the group) @@ -671,14 +590,6 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) loc_info_out.GCPL_base64 = NULL; } - if (host_header) - RV_free(host_header); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; diff --git a/src/rest_vol_link.c b/src/rest_vol_link.c index 5d0f1f87..512ed31d 100644 --- a/src/rest_vol_link.c +++ b/src/rest_vol_link.c @@ -32,7 +32,7 @@ static herr_t RV_link_iter_callback(char *HTTP_response, void *callback_data_in, static herr_t RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)(const void *, const void *), link_table_entry **link_table, size_t *num_entries, rv_hash_table_t *visited_link_table, - const char *base_URL); + RV_object_t *loc_obj); static void RV_free_link_table(link_table_entry *link_table, size_t num_entries); static herr_t RV_traverse_link_table(link_table_entry *link_table, size_t num_entries, iter_data *iter_data, const char *cur_link_rel_path); @@ -73,16 +73,14 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t RV_object_t *new_link_loc_obj = (RV_object_t *)obj; upload_info uinfo; size_t create_request_nalloc = 0; - size_t host_header_len = 0; void *hard_link_target_obj; - const char *base_URL = NULL; - char *host_header = NULL; char *create_request_body = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; char *url_encoded_link_name = NULL; int create_request_body_len = 0; int url_len = 0; - herr_t ret_value = SUCCEED; + long http_response; + herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG printf("-> Received link create call with following parameters:\n"); @@ -121,12 +119,6 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t new_link_loc_obj = (RV_object_t *)hard_link_target_obj; } /* end if */ - if (new_link_loc_obj && ((base_URL = new_link_loc_obj->domain->u.file.server_info.base_URL) == NULL)) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - - if (!base_URL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link creation requires valid server URL"); - /* Validate loc_id and check for write access on the file */ if (H5I_FILE != new_link_loc_obj->obj_type && H5I_GROUP != new_link_loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location object not a file or group"); @@ -304,23 +296,6 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t FUNC_GOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "Invalid link create type"); } /* end switch */ - /* Setup the host header */ - host_header_len = strlen(new_link_loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, new_link_loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - /* Instruct cURL that we are sending JSON */ - curl_headers = curl_slist_append(curl_headers, "Content-Type: application/json"); - /* URL-encode the name of the link to ensure that the resulting URL for the link * creation operation doesn't contain any illegal characters */ @@ -329,47 +304,27 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); /* Redirect cURL from the base URL to "/groups//links/" to create the link */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, - new_link_loc_obj->URI, url_encoded_link_name)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", new_link_loc_obj->URI, + url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "link create URL size exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG - printf("-> Link create request URL: %s\n\n", request_url); + printf("-> Link create request URL: %s\n\n", request_endpoint); #endif uinfo.buffer = create_request_body; uinfo.buffer_size = (size_t)create_request_body_len; uinfo.bytes_sent = 0; - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, new_link_loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, new_link_loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_READDATA, &uinfo)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL PUT data: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)create_request_body_len)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL PUT data size: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Creating link\n\n"); - printf(" /**********************************\\\n"); - printf("-> | Making PUT request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif + // TODO - Check this uses right filename for external links + http_response = RV_curl_put(&new_link_loc_obj->domain->u.file.server_info, request_endpoint, + new_link_loc_obj->domain->u.file.filepath_name, &uinfo, CONTENT_TYPE_JSON); - CURL_PERFORM(curl, H5E_LINK, H5E_CANTCREATE, FAIL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "can't create link"); #ifdef RV_CONNECTOR_DEBUG printf("-> Created link\n\n"); @@ -382,20 +337,9 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t if (create_request_body) RV_free(create_request_body); - if (host_header) - RV_free(host_header); if (url_encoded_link_name) curl_free(url_encoded_link_name); - /* Unset cURL UPLOAD option to ensure that future requests don't try to use PUT calls */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 0)) - FUNC_DONE_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't unset cURL PUT option: %s", curl_err_buf); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -473,13 +417,10 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t { RV_object_t *loc_obj = (RV_object_t *)obj; hbool_t empty_dirname; - size_t host_header_len = 0; - const char *base_URL = NULL; - char *host_header = NULL; char *link_dir_name = NULL; char *url_encoded_link_name = NULL; char temp_URI[URI_MAX_LENGTH]; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; int url_len = 0; herr_t ret_value = SUCCEED; @@ -491,9 +432,6 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t printf(" - Link loc_obj's domain path: %s\n\n", loc_obj->domain->u.file.filepath_name); #endif - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - switch (args->op_type) { /* H5Lget_info */ case H5VL_LINK_GET_INFO: { @@ -541,7 +479,7 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t curl, H5_rest_basename(loc_params->loc_data.loc_by_name.name), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", empty_dirname ? loc_obj->URI : temp_URI, url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -566,44 +504,9 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t } /* end switch */ /* Make a GET request to the server to retrieve the number of attributes attached to the object */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving link info at URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); /* Retrieve the link info */ if (RV_parse_response(response_buffer.buffer, NULL, link_info, RV_get_link_info_callback) < 0) @@ -654,8 +557,7 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't locate group"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", base_URL, temp_URI)) < - 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links", temp_URI)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -663,45 +565,9 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t "H5Lget_name_by_idx request URL size exceeded maximum URL size"); /* Make a GET request to the server to retrieve all of the links in the given group */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all links in group using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); if (RV_parse_response(response_buffer.buffer, &by_idx_data, &link_name_data, RV_get_link_name_by_idx_callback) < 0) @@ -759,7 +625,7 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t curl, H5_rest_basename(loc_params->loc_data.loc_by_name.name), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", empty_dirname ? loc_obj->URI : temp_URI, url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -784,45 +650,9 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t } /* end switch */ /* Make a GET request to the server to retrieve the number of attributes attached to the object */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving link value from URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); /* Retrieve the link value */ if (RV_parse_response(response_buffer.buffer, &buf_size, out_buf, RV_get_link_val_callback) < 0) @@ -840,18 +670,11 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t printf("-> Link get response buffer:\n%s\n\n", response_buffer.buffer); #endif - if (host_header) - RV_free(host_header); if (url_encoded_link_name) curl_free(url_encoded_link_name); if (link_dir_name) RV_free(link_dir_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -874,17 +697,15 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci { RV_object_t *loc_obj = (RV_object_t *)obj; hbool_t empty_dirname; - size_t host_header_len = 0; hid_t link_iter_group_id = H5I_INVALID_HID; void *link_iter_group_object = NULL; - const char *base_URL = NULL; - char *host_header = NULL; char *link_path_dirname = NULL; char temp_URI[URI_MAX_LENGTH]; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; char *url_encoded_link_name = NULL; int url_len = 0; - herr_t ret_value = SUCCEED; + long http_response; + herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG printf("-> Received link-specific call with following parameters:\n"); @@ -897,9 +718,6 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci if (H5I_FILE != loc_obj->obj_type && H5I_GROUP != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file or group"); - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - switch (args->op_type) { /* H5Ldelete */ case H5VL_LINK_DELETE: { @@ -938,7 +756,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); /* Redirect cURL from the base URL to "/groups//links/" to delete link */ - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", empty_dirname ? loc_obj->URI : temp_URI, url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -962,46 +780,11 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci FUNC_GOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "invalid loc_params type"); } /* end switch */ - /* Setup cURL to make the DELETE request */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP DELETE request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Deleting link using URL: %s\n\n", request_url); - - printf(" /*************************************\\\n"); - printf("-> | Making DELETE request to the server |\n"); - printf(" \\*************************************/\n\n"); -#endif + http_response = RV_curl_delete(&loc_obj->domain->u.file.server_info, request_endpoint, + (const char *)loc_obj->domain->u.file.filepath_name); - CURL_PERFORM(curl, H5E_LINK, H5E_CANTREMOVE, FAIL); + if (!HTTP_SUCCESS(http_response)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTREMOVE, FAIL, "can't delete link"); break; } /* H5VL_LINK_DELETE */ @@ -1009,7 +792,6 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci /* H5Lexists */ case H5VL_LINK_EXISTS: { hbool_t *ret = args->args.exists.exists; - long http_response; /* In case the user specified a path which contains multiple groups on the way to the * link in question, extract out the path to the final group in the chain */ @@ -1038,7 +820,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci curl, H5_rest_basename(loc_params->loc_data.loc_by_name.name), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links/%s", empty_dirname ? loc_obj->URI : temp_URI, url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1046,51 +828,9 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "H5Lexists request URL size exceeded maximum URL size"); - /* Setup cURL to make the GET request */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Checking for existence of link using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM_NO_ERR(curl, FAIL); - - if (CURLE_OK != curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get HTTP response code"); - - *ret = HTTP_SUCCESS(http_response); + http_response = RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON); + *ret = HTTP_SUCCESS(http_response); break; } /* H5VL_LINK_EXISTS */ @@ -1125,7 +865,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci RV_group_open(loc_obj, loc_params, ".", H5P_DEFAULT, H5P_DEFAULT, NULL))) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "can't open link iteration group"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links", loc_obj->URI)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1155,7 +895,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci H5P_DEFAULT, H5P_DEFAULT, NULL))) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "can't open link iteration group"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links", ((RV_object_t *)link_iter_group_object)->URI)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1199,45 +939,9 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci link_iter_data.iter_obj_id = link_iter_group_id; /* Make a GET request to the server to retrieve all of the links in the given group */ - - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = - curl_slist_append(curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all links in group using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); if (RV_parse_response(response_buffer.buffer, &link_iter_data, NULL, RV_link_iter_callback) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't iterate over links"); @@ -1253,28 +957,15 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci done: if (link_path_dirname) RV_free(link_path_dirname); - if (host_header) - RV_free(host_header); if (link_iter_group_id >= 0) if (H5Gclose(link_iter_group_id) < 0) FUNC_DONE_ERROR(H5E_LINK, H5E_CANTCLOSEOBJ, FAIL, "can't close link iteration group"); - /* In case a custom DELETE request was made, reset the request to NULL - * to prevent any possible future issues with requests - */ - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL)) - FUNC_DONE_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't reset cURL custom request: %s", curl_err_buf); - /* Free the escaped portion of the URL */ if (url_encoded_link_name) curl_free(url_encoded_link_name); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - PRINT_ERROR_STACK; return ret_value; @@ -1682,8 +1373,7 @@ RV_get_link_name_by_idx_callback(char *HTTP_response, void *callback_data_in, vo #endif if (RV_build_link_table(HTTP_response, by_idx_data->is_recursive, link_table_sort_func, &link_table, - &link_table_num_entries, NULL, - by_idx_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) + &link_table_num_entries, NULL, by_idx_data->iter_obj_parent) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); /* Check to make sure the index given is within bounds */ @@ -1782,8 +1472,7 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac */ if (RV_build_link_table(HTTP_response, link_iter_data->is_recursive, H5_rest_cmp_links_by_creation_order_inc, &link_table, &link_table_num_entries, - visited_link_table, - link_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) + visited_link_table, link_iter_data->iter_obj_parent) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); #ifdef RV_CONNECTOR_DEBUG @@ -1793,7 +1482,7 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac else { if (RV_build_link_table(HTTP_response, link_iter_data->is_recursive, NULL, &link_table, &link_table_num_entries, visited_link_table, - link_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) + link_iter_data->iter_obj_parent) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); } /* end else */ @@ -1847,7 +1536,7 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac static herr_t RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)(const void *, const void *), link_table_entry **link_table, size_t *num_entries, rv_hash_table_t *visited_link_table, - const char *base_URL) + RV_object_t *loc_obj) { link_table_entry *table = NULL; yajl_val parse_tree = NULL, key_obj; @@ -1857,7 +1546,7 @@ RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)( char *visit_buffer = NULL; char *link_section_start, *link_section_end; char *url_encoded_link_name = NULL; - char request_url[URL_MAX_LENGTH]; + char request_endpoint[URL_MAX_LENGTH]; herr_t ret_value = SUCCEED; if (!HTTP_response) @@ -2020,7 +1709,7 @@ RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)( curl, H5_rest_basename(YAJL_GET_STRING(link_field_obj)), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links", url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -2028,23 +1717,13 @@ RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)( FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "link GET request URL size exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all links in subgroup using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); if (RV_build_link_table(response_buffer.buffer, is_recursive, sort_func, &table[i].subgroup.subgroup_link_table, - &table[i].subgroup.num_entries, visited_link_table, base_URL) < 0) + &table[i].subgroup.num_entries, visited_link_table, loc_obj) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table for subgroup '%s'", table[i].link_name); diff --git a/src/rest_vol_object.c b/src/rest_vol_object.c index e69cad47..4a6aaa59 100644 --- a/src/rest_vol_object.c +++ b/src/rest_vol_object.c @@ -265,14 +265,12 @@ herr_t RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_args_t *args, hid_t dxpl_id, void **req) { - RV_object_t *loc_obj = (RV_object_t *)obj; - size_t host_header_len = 0; - char *host_header = NULL; - char request_url[URL_MAX_LENGTH]; - char *found_object_name = NULL; - const char *base_URL = NULL; - int url_len = 0; - herr_t ret_value = SUCCEED; + RV_object_t *loc_obj = (RV_object_t *)obj; + char request_endpoint[URL_MAX_LENGTH]; + char *found_object_name = NULL; + const char *parent_obj_type_header = NULL; + int url_len = 0; + herr_t ret_value = SUCCEED; loc_info loc_info_out; loc_info_out.GCPL_base64 = NULL; @@ -291,9 +289,6 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar H5I_DATATYPE != loc_obj->obj_type && H5I_DATASET != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file, group, dataset or committed datatype"); - if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); - switch (args->op_type) { case H5VL_OBJECT_GET_NAME: { size_t copy_size = 0; @@ -344,60 +339,17 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar * depending on the type of the object. Also set the * object's type in the H5O_info2_t struct. */ - switch (obj_type) { - case H5I_FILE: - case H5I_GROUP: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s", base_URL, - loc_obj->URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info request URL size exceeded maximum URL size"); - - break; - } /* H5I_FILE H5I_GROUP */ - - case H5I_DATATYPE: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s", base_URL, - loc_obj->URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info request URL size exceeded maximum URL size"); - - break; - } /* H5I_DATATYPE */ - - case H5I_DATASET: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s", base_URL, - loc_obj->URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); + if (RV_set_object_type_header(obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, + "target object not a group, datatype or dataset"); - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info request URL size exceeded maximum URL size"); + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s", + parent_obj_type_header, loc_obj->URI)) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - break; - } /* H5I_DATASET */ - - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, - "loc_id object is not a group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, + "H5Oget_info request URL size exceeded maximum URL size"); #ifdef RV_CONNECTOR_DEBUG printf("-> H5Oget_info(): Object type: %s\n\n", object_type_to_string(obj_type)); @@ -443,63 +395,17 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar * depending on the type of the object. Also set the * object's type in the H5O_info2_t struct. */ - switch (obj_type) { - case H5I_FILE: - case H5I_GROUP: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s", base_URL, - temp_URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR( - H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info_by_name request URL size exceeded maximum URL size"); - - break; - } /* H5I_FILE H5I_GROUP */ - - case H5I_DATATYPE: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datatypes/%s", base_URL, - temp_URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR( - H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info_by_name request URL size exceeded maximum URL size"); - - break; - } /* H5I_DATATYPE */ - - case H5I_DATASET: { - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s", base_URL, - temp_URI)) < 0) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); + if (RV_set_object_type_header(obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, + "target object not a group, datatype or dataset"); - if (url_len >= URL_MAX_LENGTH) - FUNC_GOTO_ERROR( - H5E_OBJECT, H5E_SYSERRSTR, FAIL, - "H5Oget_info_by_name request URL size exceeded maximum URL size"); + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s", + parent_obj_type_header, temp_URI)) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); - break; - } /* H5I_DATASET */ - - case H5I_ATTR: - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_VFL: - case H5I_VOL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, - "loc_id object is not a group, datatype or dataset"); - } /* end switch */ + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, + "H5Oget_info_by_name request URL size exceeded maximum URL size"); break; } /* H5VL_OBJECT_BY_NAME */ @@ -512,8 +418,7 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar htri_t search_ret; char temp_URI[URI_MAX_LENGTH]; - const char *request_idx_type = NULL; - const char *parent_obj_type_header = NULL; + const char *request_idx_type = NULL; obj_type = H5I_UNINIT; @@ -561,64 +466,27 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_PATH, FAIL, "can't locate parent object"); - /* Setup the host header */ - host_header_len = strlen(loc_obj->domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append( - curl_headers, strncat(host_header, loc_obj->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (RV_set_object_type_header(obj_type, &parent_obj_type_header) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, + "parent object not a group, datatype or dataset"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links?%s", base_URL, - temp_URI, request_idx_type)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s/links?%s", + parent_obj_type_header, temp_URI, request_idx_type)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, - loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, - loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link"); if (0 > RV_parse_response(response_buffer.buffer, (void *)&loc_params->loc_data.loc_by_idx, &found_object_name, RV_copy_link_name_by_index)) FUNC_GOTO_ERROR(H5E_LINK, H5E_PARSEERROR, FAIL, "failed to retrieve link names"); - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - /* Use name of link to get object URI for final request */ if (loc_info_out.GCPL_base64) { @@ -636,7 +504,7 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar FUNC_GOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "object at index not a group, datatype or dataset"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s", base_URL, + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s", parent_obj_type_header, loc_info_out.URI)) < 0) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -653,47 +521,9 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar } /* end switch */ /* Make a GET request to the server to retrieve the number of attributes attached to the object */ - - /* Setup the host header */ - host_header_len = strlen(loc_info_out.domain->u.file.filepath_name) + strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append(curl_headers, - strncat(host_header, loc_info_out.domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTSET, FAIL, - "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving object info using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - CURL_PERFORM(curl, H5E_OBJECT, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTGET, FAIL, "can't get object"); /* Retrieve the attribute count for the object */ if (RV_parse_response(response_buffer.buffer, NULL, obj_info, RV_get_object_info_callback) < 0) @@ -718,14 +548,6 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar } /* end switch */ done: - if (host_header) - RV_free(host_header); - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } /* end if */ - if (found_object_name) { RV_free(found_object_name); found_object_name = NULL; @@ -764,11 +586,8 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s RV_object_t *attr_object = NULL; hid_t iter_object_id = H5I_INVALID_HID; char visit_by_name_URI[URI_MAX_LENGTH]; - char request_url[URL_MAX_LENGTH]; - char *host_header = NULL; - int url_len = 0; - size_t host_header_len = 0; - + char request_endpoint[URL_MAX_LENGTH]; + int url_len = 0; #ifdef RV_CONNECTOR_DEBUG printf("-> Received object-specific call with following parameters:\n"); printf(" - Object-specific call type: %s\n", object_specific_type_to_string(args->op_type)); @@ -1041,8 +860,7 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s /* To build object table, information about parent object will be needed */ object_iter_data.iter_obj_parent = iter_object; - if (url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s", - iter_object->domain->u.file.server_info.base_URL, object_type_header, + if (url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s", object_type_header, object_iter_data.iter_obj_parent->URI) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1093,49 +911,9 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s /* Unlike H5Lvisit, H5Ovisit executes the provided callback on the directly specified object. */ /* Make GET request to server */ - - /* Setup the host header */ - host_header_len = strlen(object_iter_data.iter_obj_parent->domain->u.file.filepath_name) + - strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append( - curl_headers, - strncat(host_header, object_iter_data.iter_obj_parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); - if (CURLE_OK != - curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all links in group using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif - - /* Do a first request to populate obj info in order to execute the callback on the top-level given - * object */ - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link to object"); if (RV_parse_response(response_buffer.buffer, NULL, &oinfo, RV_get_object_info_callback) < 0) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PARSEERROR, FAIL, "failed to get object info"); @@ -1156,22 +934,18 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s switch (iter_object_type) { case H5I_FILE: case H5I_GROUP: - if (url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s%s", - object_iter_data.iter_obj_parent->domain->u.file.server_info.base_URL, - object_type_header, object_iter_data.iter_obj_parent->URI, - (!strcmp(object_type_header, "groups") ? "/links" : "")) < 0) + if (url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/%s/%s%s", object_type_header, + object_iter_data.iter_obj_parent->URI, + (!strcmp(object_type_header, "groups") ? "/links" : "")) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "H5Oiterate/visit request URL size exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (RV_curl_get(&loc_obj->domain->u.file.server_info, request_endpoint, + loc_obj->domain->u.file.filepath_name, CONTENT_TYPE_JSON) < 0) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link to object"); if (RV_parse_response(response_buffer.buffer, &object_iter_data, NULL, RV_object_iter_callback) < 0) @@ -1205,9 +979,6 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s } /* end switch */ done: - if (host_header) - RV_free(host_header); - RV_free(attr_loc_params); if (attr_object) @@ -1566,12 +1337,12 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func char *visit_buffer = NULL; char *link_section_start, *link_section_end; char *url_encoded_link_name = NULL; - char request_url[URL_MAX_LENGTH]; - herr_t ret_value = SUCCEED; - int url_len = 0; - H5I_type_t obj_type = H5I_UNINIT; - char *host_header = NULL; - RV_object_t *subgroup = NULL; + char request_endpoint[URL_MAX_LENGTH]; + herr_t ret_value = SUCCEED; + int url_len = 0; + H5I_type_t obj_type = H5I_UNINIT; + RV_object_t *subgroup = NULL; + long response_code; if (!HTTP_response) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "HTTP response was NULL"); @@ -1789,72 +1560,21 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func curl, H5_rest_basename(YAJL_GET_STRING(link_field_obj)), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", - object_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL, - url_encoded_link_name)) < 0) + if ((url_len = snprintf(request_endpoint, URL_MAX_LENGTH, "/groups/%s/links", + url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "link GET request URL size exceeded maximum URL size"); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", - curl_err_buf); - - /* Set up host header */ - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } - - size_t host_header_len = - strlen(object_iter_data->iter_obj_parent->domain->u.file.filepath_name) + - strlen(host_string) + 1; - if (NULL == (host_header = (char *)RV_malloc(host_header_len))) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, - "can't allocate space for request Host header"); - - strcpy(host_header, host_string); - - curl_headers = curl_slist_append( - curl_headers, - strncat(host_header, object_iter_data->iter_obj_parent->domain->u.file.filepath_name, - host_header_len - strlen(host_string) - 1)); - - /* Disable use of Expect: 100 Continue HTTP response */ - curl_headers = curl_slist_append(curl_headers, "Expect:"); - - if (CURLE_OK != - curl_easy_setopt( - curl, CURLOPT_USERNAME, - object_iter_data->iter_obj_parent->domain->u.file.server_info.username)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", - curl_err_buf); - if (CURLE_OK != - curl_easy_setopt( - curl, CURLOPT_PASSWORD, - object_iter_data->iter_obj_parent->domain->u.file.server_info.password)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL password: %s", - curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) - FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", - curl_err_buf); -#ifdef RV_CONNECTOR_DEBUG - printf("-> Retrieving all links in subgroup using URL: %s\n\n", request_url); - - printf(" /**********************************\\\n"); - printf("-> | Making GET request to the server |\n"); - printf(" \\**********************************/\n\n"); -#endif + response_code = RV_curl_get( + &object_iter_data->iter_obj_parent->domain->u.file.server_info, request_endpoint, + object_iter_data->iter_obj_parent->domain->u.file.filepath_name, CONTENT_TYPE_JSON); - CURL_PERFORM(curl, H5E_LINK, H5E_CANTGET, FAIL); + if (!(HTTP_SUCCESS(response_code))) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTGET, FAIL, "can't get object: HTTP %ld", + response_code); /* Use the group we are recursing into as the parent during the recursion */ if ((subgroup = RV_malloc(sizeof(RV_object_t))) == NULL) @@ -1905,15 +1625,6 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func /* Continue on to the next link subsection */ link_section_start = link_section_end + 1; - - if (host_header) { - RV_free(host_header); - host_header = NULL; - } - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } } /* end for */ #ifdef RV_CONNECTOR_DEBUG @@ -1942,12 +1653,6 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func yajl_tree_free(parse_tree); if (visit_buffer) RV_free(visit_buffer); - if (host_header) - RV_free(host_header); - if (curl_headers) { - curl_slist_free_all(curl_headers); - curl_headers = NULL; - } return ret_value; } /* end RV_build_object_table */