#define _POSIX_C_SOURCE 200809L #include #include #include #include "string-util.h" #include "auth.h" #define BUFFER_SIZE (256 * 1024) #define AUTH_HEADER_STR_PREFIX "Authorization: Bearer " int http_init() { return curl_global_init(CURL_GLOBAL_ALL); } void 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) { fprintf(stderr, "error: too small buffer\n"); return 0; } memcpy(result->data + result->pos, ptr, size * nmemb); result->pos += size * nmemb; return size * nmemb; } char *get_request(const char *url) { 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 (auth_token) { char *auth_header_val = malloc(strlen(AUTH_HEADER_STR_PREFIX) + strlen(auth_token) + 1); strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, sizeof(auth_header_val)); strlcat(auth_header_val, auth_token, sizeof(auth_header_val)); 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 != 0) { fprintf(stderr, "get_request(): unable to request data from %s: %s\n", url, curl_easy_strerror(status)); goto error; } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); if (code != 200) { fprintf(stderr, "error: server responded with code %ld\n", 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 *post_request(const char *url, 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 (auth_token) { char *auth_header_val = malloc(strlen(AUTH_HEADER_STR_PREFIX) + strlen(auth_token) + 1); strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, sizeof(auth_header_val)); strlcat(auth_header_val, auth_token, sizeof(auth_header_val)); 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); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); status = curl_easy_perform(curl); if (status != 0) { fprintf(stderr, "post_request(): unable to request data from %s: %s\n", url, curl_easy_strerror(status)); goto error; } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); if (code != 200) { fprintf(stderr, "error: server responded with code %ld\n", 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; }