diff options
Diffstat (limited to 'src/http.c')
-rw-r--r-- | src/http.c | 117 |
1 files changed, 110 insertions, 7 deletions
@@ -1,6 +1,8 @@ #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" @@ -41,6 +43,7 @@ static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) char *get_request(const char *url) { + CURL *curl = NULL; CURLcode status; struct curl_slist *headers = NULL; @@ -58,8 +61,10 @@ char *get_request(const char *url) 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)); + 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); } @@ -71,7 +76,8 @@ char *get_request(const char *url) 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)); + fprintf(stderr, "get_request(): unable to request data from %s: %s\n", + url, curl_easy_strerror(status)); goto error; } @@ -105,7 +111,6 @@ char *post_request(const char *url, char *post_data) char *data = NULL; long code; - curl = curl_easy_init(); if (!curl) goto error; @@ -117,8 +122,10 @@ char *post_request(const char *url, char *post_data) 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)); + 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); } @@ -135,7 +142,8 @@ char *post_request(const char *url, char *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)); + fprintf(stderr, "post_request(): unable to request data from %s: %s\n", + url, curl_easy_strerror(status)); goto error; } @@ -160,3 +168,98 @@ error: curl_easy_cleanup(curl); return NULL; } + +struct post_request_arg { + char *url; + char *post_data; + void (*callback)(char *); +}; + +void *post_one_url(void *arg) +{ + + struct post_request_arg *req_args = (struct post_request_arg *)arg; + 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 (req_args->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, req_args->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, req_args->post_data); + + status = curl_easy_perform(curl); + if (status != 0) { + fprintf(stderr, "post_request(): unable to request data from %s: %s\n", + req_args->url, curl_easy_strerror(status)); + goto error; + } + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); + if (code != 200) { + fprintf(stderr, "post_request(): server responded with code %ld\n", code); + goto error; + } + + data[write_result.pos] = '\0'; + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + + (*(req_args->callback))(data); + return NULL; + +error: + if (data) + free(data); + if (headers) + curl_slist_free_all(headers); + if (curl) + curl_easy_cleanup(curl); + + (*(req_args->callback))(NULL); + return NULL; +} + +int http_post_async(char *url, char *post_data, void (*callback)(char *)) +{ + struct post_request_arg *arg; + pthread_t t; + + arg = calloc(1, sizeof(struct post_request_arg)); + if (!arg) { + err(1, "http_post_async(): calloc failed"); + return -1; + } + arg->url = url; + arg->post_data = post_data; + arg->callback = callback; + + return pthread_create(&t, NULL, post_one_url, arg); +} |