summaryrefslogtreecommitdiff
path: root/libgs/src/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgs/src/http.c')
-rw-r--r--libgs/src/http.c178
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;
+}