#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include "string-util.h" #include "auth.h" #include "client.h" #include "log.h" #define BUFFER_SIZE (256 * 1024) #define AUTH_HEADER_STR_PREFIX "Authorization: Bearer " int gs_http_init() { if (curl_global_init(CURL_GLOBAL_ALL)) { gs_log(GS_WARNING, "http_init", "failed to init curl"); return -1; } return 0; } void gs_http_cleanup() { curl_global_cleanup(); return; } struct write_result { char *data; int pos; }; static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) { struct write_result *result = (struct write_result *)stream; if (result->pos + size * nmemb >= BUFFER_SIZE - 1) { gs_log(GS_WARNING, "write_response", "buffer too small"); return 0; } memcpy(result->data + result->pos, ptr, size * nmemb); result->pos += size * nmemb; return size * nmemb; } char *gs_http_get(const char *url, const char *token) { CURL *curl = NULL; CURLcode status; struct curl_slist *headers = NULL; char *data = NULL; long code; curl = curl_easy_init(); if (!curl) goto error; data = malloc(BUFFER_SIZE); if (!data) goto error; struct write_result write_result = {.data = data, .pos = 0}; if (token) { size_t s = strlen(AUTH_HEADER_STR_PREFIX) + strlen(token) + 1; char auth_header_val[s]; strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, s); strlcat(auth_header_val, token, s); headers = curl_slist_append(headers, auth_header_val); } curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result); status = curl_easy_perform(curl); if (status) { gs_log(GS_WARNING, "get_request", "unable to request data from %s: %s", url, curl_easy_strerror(status)); goto error; } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); if (code != 200) { gs_log(GS_WARNING, "get_request", "server responded with code %ld", code); goto error; } data[write_result.pos] = '\0'; curl_slist_free_all(headers); curl_easy_cleanup(curl); return data; error: if (data) free(data); if (headers) curl_slist_free_all(headers); if (curl) curl_easy_cleanup(curl); return NULL; } char *gs_http_post(const char *url, const char *token, const char *post_data) { CURL *curl = NULL; CURLcode status; struct curl_slist *headers = NULL; char *data = NULL; long code; curl = curl_easy_init(); if (!curl) goto error; data = malloc(BUFFER_SIZE); if (!data) goto error; struct write_result write_result = {.data = data, .pos = 0}; if (token) { size_t s = strlen(AUTH_HEADER_STR_PREFIX) + strlen(token) + 1; char auth_header_val[s]; strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, s); strlcat(auth_header_val, token, s); headers = curl_slist_append(headers, auth_header_val); } if (post_data) { char *content_type_header_val = "Content-Type: application/json"; headers = curl_slist_append(headers, content_type_header_val); } curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result); if (post_data) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); status = curl_easy_perform(curl); if (status) { gs_log(GS_WARNING, "post_request", "unable to request data from %s: %s", url, curl_easy_strerror(status)); goto error; } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); if (code != 200) { gs_log(GS_WARNING, "post_request", "server responded with code %ld", code); goto error; } data[write_result.pos] = '\0'; curl_slist_free_all(headers); curl_easy_cleanup(curl); return data; error: if (data) free(data); if (headers) curl_slist_free_all(headers); if (curl) curl_easy_cleanup(curl); return NULL; }