-
-
Save svagionitis/6eea918d94bae34a7456 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
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
/** | |
* 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> | |
struct curl_fetch_payload { | |
char *payload; | |
size_t size; | |
}; | |
static size_t | |
curl_fetch_callback (void *contents, size_t size, size_t nmemb, void *userp) | |
{ | |
size_t realsize = size * nmemb; | |
struct curl_fetch_payload *mem = (struct curl_fetch_payload *) userp; | |
char *tmp = NULL; | |
tmp = realloc (mem->payload, mem->size + realsize + 1); | |
if (tmp != NULL) { | |
mem->payload = tmp; | |
} else { | |
if (mem->payload) { | |
free (mem->payload); | |
mem->payload = NULL; | |
} | |
return 0; | |
} | |
/* Copy contents to buffer */ | |
memcpy (&(mem->payload[mem->size]), contents, realsize); | |
/* Set ne buffer size */ | |
mem->size += realsize; | |
/* Null termination */ | |
mem->payload[mem->size] = 0; | |
return realsize; | |
} | |
/* fetch and return url body via curl */ | |
static CURLcode | |
fetch_url_curl (CURL *curl_ctx, const char *url, struct curl_fetch_payload *fetch) | |
{ | |
CURLcode rcode; | |
/* will be grown as needed by realloc from the callback */ | |
fetch->payload = malloc (1); | |
if (fetch->payload == NULL) { | |
return CURLE_OUT_OF_MEMORY; | |
} | |
/* init size */ | |
fetch->size = 0; | |
/* set url to fetch */ | |
curl_easy_setopt (curl_ctx, CURLOPT_URL, url); | |
/* set calback function */ | |
curl_easy_setopt (curl_ctx, CURLOPT_WRITEFUNCTION, curl_fetch_callback); | |
/* pass fetch struct pointer */ | |
curl_easy_setopt (curl_ctx, CURLOPT_WRITEDATA, (void *) fetch); | |
/* some servers don't like requests that are made without a user-agent | |
field, so we provide one */ | |
curl_easy_setopt (curl_ctx, CURLOPT_USERAGENT, "libcurl-agent/1.0"); | |
/* set timeout to 90 seconds */ | |
curl_easy_setopt (curl_ctx, CURLOPT_TIMEOUT, 90); | |
/* enable location redirects */ | |
curl_easy_setopt (curl_ctx, CURLOPT_FOLLOWLOCATION, 1); | |
/* set maximum allowed redirects */ | |
curl_easy_setopt (curl_ctx, CURLOPT_MAXREDIRS, 1); | |
/* make connection get closed at once after use */ | |
curl_easy_setopt (curl_ctx, CURLOPT_FORBID_REUSE, 1); | |
/* fetch the url */ | |
rcode = curl_easy_perform (curl_ctx); | |
return rcode; | |
} | |
int | |
post_json_curl (char **response, size_t *response_sz, const char *url, const char *json) | |
{ | |
int ret = 0; | |
CURL *curl_ctx = NULL; | |
CURLcode rcode = 0, http_code = 0; | |
struct curl_slist *headers = NULL; | |
struct curl_fetch_payload fetch_response; | |
char *tmp; | |
if ( *response ) | |
*response = NULL; | |
if (url == NULL || strlen (url) == 0) { | |
fprintf (stderr, "No URL specified.\n"); | |
ret = -1; | |
goto out; | |
} | |
if (json == NULL || strlen (json) == 0) { | |
fprintf (stderr, "No json object specified.\n"); | |
ret = -1; | |
goto out; | |
} | |
curl_ctx = curl_easy_init(); | |
if (curl_ctx == NULL) { | |
fprintf (stderr, "Failed to create curl handle in fetch_session\n"); | |
ret = -1; | |
goto out; | |
} | |
/* set content type */ | |
headers = curl_slist_append (headers, "Accept: application/json"); | |
headers = curl_slist_append (headers, "Content-Type: application/json"); | |
/* set curl options */ | |
curl_easy_setopt (curl_ctx, CURLOPT_CUSTOMREQUEST, "POST"); | |
curl_easy_setopt (curl_ctx, CURLOPT_HTTPHEADER, headers); | |
curl_easy_setopt (curl_ctx, CURLOPT_POSTFIELDS, json); | |
/* fetch page and capture return code */ | |
rcode = fetch_url_curl (curl_ctx, url, &fetch_response); | |
tmp = fetch_response.payload; | |
if (rcode != CURLE_OK || fetch_response.size < 1) { | |
fprintf (stderr, "Failed to post data to %s -- %s\n", url, curl_easy_strerror (rcode)); | |
ret = rcode; | |
goto free_payload; | |
} else { | |
/* Get the HTTP code */ | |
curl_easy_getinfo (curl_ctx, CURLINFO_RESPONSE_CODE, &http_code); | |
fetch_response.payload = tmp; | |
if (http_code != (CURLcode) 200) | |
ret += (int) http_code; | |
} | |
if (fetch_response.payload == NULL) { | |
fprintf (stderr, "Failed to populate payload.\n"); | |
ret = -1; | |
goto free_payload; | |
} | |
*response = fetch_response.payload; | |
*response_sz = fetch_response.size; | |
goto out; | |
free_payload: | |
if (fetch_response.payload) { | |
free (fetch_response.payload); | |
fetch_response.payload = NULL; | |
} | |
out: | |
if (curl_ctx) { | |
curl_easy_cleanup (curl_ctx); | |
curl_ctx = NULL; | |
} | |
if (headers) { | |
curl_slist_free_all (headers); | |
headers = NULL; | |
} | |
return ret; | |
} | |
void | |
usage(char *argv0) | |
{ | |
fprintf(stdout, "Usage: %s <URL> <JSON to POST>\n", argv0); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
char *response = NULL; | |
size_t response_sz = 0; | |
if (argc != 3) { | |
usage(argv[0]); | |
return -1; | |
} | |
int ret = post_json_curl (&response, &response_sz, argv[1], argv[2]); | |
if (ret < 0) { | |
fprintf(stderr, "Error posting '%s' to '%s'\n", argv[2], argv[1]); | |
return -1; | |
} | |
fprintf (stdout, "Response: '%s' -- Size: %zu\n", response, response_sz); | |
/* exit */ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment