diff options
Diffstat (limited to 'libgs/src/http.c')
-rw-r--r-- | libgs/src/http.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/libgs/src/http.c b/libgs/src/http.c new file mode 100644 index 0000000..e1224ff --- /dev/null +++ b/libgs/src/http.c @@ -0,0 +1,178 @@ +#define _POSIX_C_SOURCE 200809L +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <err.h> +#include <curl/curl.h> +#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; +} |