Skip to content

Instantly share code, notes, and snippets.

@amirrajan
Forked from aaronhurt/curltest.c
Created November 24, 2021 19:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amirrajan/f7604aba4bd9312df38d7a8f3774947c to your computer and use it in GitHub Desktop.
Save amirrajan/f7604aba4bd9312df38d7a8f3774947c to your computer and use it in GitHub Desktop.
example code using libcurl and json-c to post and parse a return from http://jsonplaceholder.typicode.com
/**
* example C code using libcurl and json-c
* to post and return a payload using
* http://jsonplaceholder.typicode.com
*
* License:
*
* This code is licensed under MIT license
* https://opensource.org/licenses/MIT
*
* Requirements:
*
* json-c - https://github.com/json-c/json-c
* libcurl - http://curl.haxx.se/libcurl/c
*
* Build:
*
* cc curltest.c -lcurl -ljson-c -o curltest
*
* Run:
*
* ./curltest
*
*/
/* standard includes */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
/* json-c (https://github.com/json-c/json-c) */
#include <json-c/json.h>
/* libcurl (http://curl.haxx.se/libcurl/c) */
#include <curl/curl.h>
/* holder for curl fetch */
struct curl_fetch_st {
char *payload;
size_t size;
};
/* callback for curl fetch */
size_t curl_callback (void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb; /* calculate buffer size */
struct curl_fetch_st *p = (struct curl_fetch_st *) userp; /* cast pointer to fetch struct */
/* expand buffer using a temporary pointer to avoid memory leaks */
char * temp = realloc(p->payload, p->size + realsize + 1);
/* check allocation */
if (temp == NULL) {
/* this isn't good */
fprintf(stderr, "ERROR: Failed to expand buffer in curl_callback");
/* free buffer */
free(p->payload);
/* return */
return 1;
}
/* assign payload */
p->payload = temp;
/* copy contents to buffer */
memcpy(&(p->payload[p->size]), contents, realsize);
/* set new buffer size */
p->size += realsize;
/* ensure null termination */
p->payload[p->size] = 0;
/* return size */
return realsize;
}
/* fetch and return url body via curl */
CURLcode curl_fetch_url(CURL *ch, const char *url, struct curl_fetch_st *fetch) {
CURLcode rcode; /* curl result code */
/* init payload */
fetch->payload = (char *) calloc(1, sizeof(fetch->payload));
/* check payload */
if (fetch->payload == NULL) {
/* log error */
fprintf(stderr, "ERROR: Failed to allocate payload in curl_fetch_url");
/* return error */
return CURLE_FAILED_INIT;
}
/* init size */
fetch->size = 0;
/* set url to fetch */
curl_easy_setopt(ch, CURLOPT_URL, url);
/* set calback function */
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, curl_callback);
/* pass fetch struct pointer */
curl_easy_setopt(ch, CURLOPT_WRITEDATA, (void *) fetch);
/* set default user agent */
curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl-agent/1.0");
/* set timeout */
curl_easy_setopt(ch, CURLOPT_TIMEOUT, 15);
/* enable location redirects */
curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
/* set maximum allowed redirects */
curl_easy_setopt(ch, CURLOPT_MAXREDIRS, 1);
/* fetch the url */
rcode = curl_easy_perform(ch);
/* return */
return rcode;
}
int main(int argc, char *argv[]) {
CURL *ch; /* curl handle */
CURLcode rcode; /* curl result code */
json_object *json; /* json post body */
enum json_tokener_error jerr = json_tokener_success; /* json parse error */
struct curl_fetch_st curl_fetch; /* curl fetch struct */
struct curl_fetch_st *cf = &curl_fetch; /* pointer to fetch struct */
struct curl_slist *headers = NULL; /* http headers to send with request */
/* url to test site */
char *url = "http://jsonplaceholder.typicode.com/posts/";
/* init curl handle */
if ((ch = curl_easy_init()) == NULL) {
/* log error */
fprintf(stderr, "ERROR: Failed to create curl handle in fetch_session");
/* return error */
return 1;
}
/* set content type */
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
/* create json object for post */
json = json_object_new_object();
/* build post data */
json_object_object_add(json, "title", json_object_new_string("testies"));
json_object_object_add(json, "body", json_object_new_string("testies ... testies ... 1,2,3"));
json_object_object_add(json, "userId", json_object_new_int(133));
/* set curl options */
curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(ch, CURLOPT_POSTFIELDS, json_object_to_json_string(json));
/* fetch page and capture return code */
rcode = curl_fetch_url(ch, url, cf);
/* cleanup curl handle */
curl_easy_cleanup(ch);
/* free headers */
curl_slist_free_all(headers);
/* free json object */
json_object_put(json);
/* check return code */
if (rcode != CURLE_OK || cf->size < 1) {
/* log error */
fprintf(stderr, "ERROR: Failed to fetch url (%s) - curl said: %s",
url, curl_easy_strerror(rcode));
/* return error */
return 1;
}
/* check payload */
if (cf->payload != NULL) {
/* print result */
printf("CURL Returned: \n%s\n", cf->payload);
/* parse return */
json = json_tokener_parse_verbose(cf->payload, &jerr);
/* free payload */
free(cf->payload);
} else {
/* error */
fprintf(stderr, "ERROR: Failed to populate payload");
/* free payload */
free(cf->payload);
/* return */
return 1;
}
/* check error */
if (jerr != json_tokener_success) {
/* error */
fprintf(stderr, "ERROR: Failed to parse json string");
/* free json object */
json_object_put(json);
/* return */
return 1;
}
/* debugging */
printf("Parsed JSON: %s\n", json_object_to_json_string(json));
/* free json object before return */
json_object_put(json);
/* exit */
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment