Skip to content

Instantly share code, notes, and snippets.

@zerdnem
Forked from aaronhurt/curltest.c
Created May 28, 2019 11:22
Show Gist options
  • Save zerdnem/dba0bda6ec5d3caa678a376cbe1b6576 to your computer and use it in GitHub Desktop.
Save zerdnem/dba0bda6ec5d3caa678a376cbe1b6576 to your computer and use it in GitHub Desktop.

Revisions

  1. @aaronhurt aaronhurt created this gist Sep 18, 2014.
    208 changes: 208 additions & 0 deletions curltest.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,208 @@
    /**
    * example C code using libcurl and json-c
    * to post and return a payload using
    * http://jsonplaceholder.typicode.com
    *
    * 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 */
    p->payload = (char *) realloc(p->payload, p->size + realsize + 1);

    /* check buffer */
    if (p->payload == NULL) {
    /* this isn't good */
    fprintf(stderr, "ERROR: Failed to expand buffer in curl_callback");
    /* free buffer */
    free(p->payload);
    /* return */
    return -1;
    }

    /* 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, 5);

    /* 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 2;
    }

    /* 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 3;
    }

    /* 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 4;
    }

    /* debugging */
    printf("Parsed JSON: %s\n", json_object_to_json_string(json));

    /* exit */
    return 0;
    }