-
-
Save opsJson/e50d3698f2a31dfb6510f79b074af77e to your computer and use it in GitHub Desktop.
C interface for libcurl.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _GO_H_ | |
#define _GO_H_ | |
#include <curl/curl.h> | |
typedef struct { | |
char *headers; | |
char *body; | |
CURL *handle; | |
long int statuscode; | |
} GO_Response; | |
struct _GO_STRING { | |
char *ptr; | |
unsigned int size; | |
}; | |
int _go_args_count(char *arg, ...) { | |
va_list args; | |
int i, size, count; | |
char flag; | |
va_start(args, arg); | |
if (va_arg(args, char *) == NULL) return 0; | |
va_end(args); | |
size = strlen(arg); | |
count = 1; | |
flag = 0; | |
if (size == 2) return 0; | |
for (i=0; i<size; i++) { | |
if ((i == 0 && arg[i] == '\"') || (i > 0 && arg[i] == '\"' && arg[i-1] != '\\')) { | |
flag = !flag; | |
} | |
if (flag) continue; | |
if (arg[i] == ',') count++; | |
} | |
return count; | |
} | |
static size_t _go_writefunction(void *data, size_t size, size_t nmemb, void *clientp) { | |
struct _GO_STRING *str = (struct _GO_STRING*)clientp; | |
char *aux; | |
if (str->size == 0) { | |
str->size = size * nmemb + 1; | |
str->ptr = malloc(str->size); | |
if (!str->ptr) return -1; | |
strncpy(str->ptr, data, str->size); | |
} | |
else { | |
str->size += size * nmemb; | |
aux = realloc(str->ptr, str->size); | |
if (!aux) { | |
free(str->ptr); | |
return -1; | |
} | |
str->ptr = aux; | |
strncat(str->ptr, data, size * nmemb); | |
} | |
return size * nmemb; | |
} | |
void GO_free(GO_Response *response) { | |
if (!response) return; | |
free(response->headers); | |
free(response->body); | |
free(response); | |
} | |
GO_Response *GO(char *method, char *url, char *body, curl_off_t size, int args_count, ...) { | |
int i; | |
CURL *curl; | |
CURLcode res; | |
va_list args; | |
GO_Response *response; | |
struct curl_slist *aux, *chunk = NULL; | |
struct _GO_STRING response_body = {0}, response_headers = {0}; | |
if (!method || !url) return NULL; | |
va_start(args, args_count); | |
for (i=0; i<args_count; i++) { | |
aux = curl_slist_append(chunk, va_arg(args, char*)); | |
if (!aux) { | |
if (chunk) curl_slist_free_all(chunk); | |
return NULL; | |
} | |
chunk = aux; | |
} | |
va_end(args); | |
curl_global_init(CURL_GLOBAL_ALL); | |
curl = curl_easy_init(); | |
if (!curl) { | |
curl_global_cleanup(); | |
return NULL; | |
} | |
if (strcmp(method, "WS") == 0 || strcmp(method, "WSS") == 0) { | |
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); | |
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); | |
} | |
else curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method); | |
curl_easy_setopt(curl, CURLOPT_URL, url); | |
if (size == -1) { | |
size = strlen(body); | |
} | |
if (size != 0) { | |
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | |
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, size); | |
} | |
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); | |
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, _go_writefunction); | |
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response_headers); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _go_writefunction); | |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_body); | |
curl_easy_setopt(curl, CURLOPT_CAINFO , "cacert.pem"); | |
res = curl_easy_perform(curl); | |
if (chunk) curl_slist_free_all(chunk); | |
if (res != CURLE_OK) { | |
curl_easy_cleanup(curl); | |
curl_global_cleanup(); | |
return NULL; | |
} | |
if ((response = calloc(1, sizeof(GO_Response))) == NULL) return NULL; | |
response->handle = curl; | |
if (response_headers.size > 0) { | |
response->headers = response_headers.ptr; | |
response->headers[response_headers.size-1] = 0; | |
} | |
if (response_body.size > 0) { | |
response->body = response_body.ptr; | |
response->body[response_body.size-1] = 0; | |
} | |
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response->statuscode); | |
if (strcmp(method, "WS") == 0 || strcmp(method, "WSS") == 0) { | |
return response; | |
} | |
curl_easy_cleanup(curl); | |
curl_global_cleanup(); | |
return response; | |
} | |
#define GO(method, url, body, size, ...) GO(method, url, body, size, _go_args_count(#__VA_ARGS__, __VA_ARGS__), __VA_ARGS__) | |
#endif /* _GO_H_ */ | |
/*/////////////////////////////////// | |
Testing: | |
///////////////////////////////////*/ | |
int main(void) { | |
GO_Response *r = GO("GET", "https://github.com/", "", -1, NULL); | |
printf("Headers: %s\n\n", r->headers); | |
printf("Body: %s\n\n", r->body); | |
printf("Status Code: %i\n", (int)r->statuscode); | |
GO_free(r); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment