Receive http get response JSON to buffer using curl API – C program

Below C program provides API’s for receiving http GET response JSON to C buffer which you can then parse using JSON parsing library like JSMN as we mentioned in our another post.

$ vim receive_http_get_response.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <unistd.h>
#include <stdbool.h>
#include <getopt.h>

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 */

	p->payload = (char *) realloc(p->payload, p->size + realsize + 1);
	if (p->payload == NULL) {
		fprintf(stderr, "ERROR: Failed to expand buffer in curl_callback");
		free(p->payload);
		return -1;
	}

	/* copy contents to buffer */
	memcpy(&(p->payload[p->size]), contents, realsize);
	p->size += realsize;
	p->payload[p->size] = 0;
	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 */

	fetch->payload = (char *) calloc(1, sizeof(fetch->payload));
	if (fetch->payload == NULL) {
		fprintf(stderr, "ERROR: Failed to allocate payload in curl_fetch_url");
		return CURLE_FAILED_INIT;
	}

	fetch->size = 0;
	curl_easy_setopt(ch, CURLOPT_URL, url);
	curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, curl_callback);
	curl_easy_setopt(ch, CURLOPT_WRITEDATA, (void *) fetch);
	curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl-agent/1.0");
	curl_easy_setopt(ch, CURLOPT_TIMEOUT, 5);
	curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(ch, CURLOPT_MAXREDIRS, 1);

	/* fetch the url */
	rcode = curl_easy_perform(ch);
	return rcode;
}

struct curl_fetch_st curl_fetch;                        /* curl fetch struct */

char *curl_receive_reply_json_to_buffer(char *url, char *userpwd) {
	CURL *ch;                                               /* curl handle */
	CURLcode rcode;                                         /* curl result code */
	struct curl_fetch_st *cf = &curl_fetch;                 /* pointer to fetch struct */
	struct curl_slist *headers = NULL;                      /* http headers to send with request */

	/*TODO: when to free above malloced url*/

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

	/* set content type */
	headers = curl_slist_append(headers, "Accept: application/json");
	headers = curl_slist_append(headers, "Content-Type: application/json");

	curl_easy_setopt(ch, CURLOPT_HTTPGET, 1L);

	if (userpwd != NULL) { 
		curl_easy_setopt(ch, CURLOPT_USERPWD, userpwd);
		curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
		curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 0);
	}
    
	/* 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);
	/* 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 NULL; // TODO: how to handle "curl said: Timeout was reached"
	}
    
	/* check payload */
	if (cf->payload != NULL) {
		/* print result */
		return cf->payload;
	}

	/* error */
	fprintf(stderr, "ERROR: Failed to populate payload");
	/* free payload */
	free(cf->payload);
	/* return */
	return NULL;
}

char *curl_download_json_to_buffer(char *remote_url) {
	char *reply_json_received;
	int wait_count = 0;

	while(wait_count < 10) {
		reply_json_received = curl_receive_reply_json_to_buffer(remote_url, NULL);
		if (json == NULL) {
			i++;
			printf("failed for %d th time, retrying after 3 sec...\n", i);
			sleep(5); //sleep for 5 sec and retry
			continue;
		} else
			break;
	}

	return reply_json_received;
}


lynxbee_ezoic

Subscribe with Valid Email Id to receive updates in Inbox. ( Secured by Google FeedBurner )

   


Leave a Comment

Android Android Build system Android Commands Android Java Applications Application Libraries Application Stack / User Interface Bash / Shell Scripts Bluetooth driver Cloud Technologies Commands and Packages Compilation Content Management System Core Kernel C Programs Development & Build Development, Debugging and Performance Tools Development Environment Setup Django & REST Api Errors & Failures Git Hardware Platforms HTML JAVA Programs Linux, OS Concepts and Networking Linux Device Drivers Linux Host, Ubuntu, SysAdmin Linux Kernel Linux Networking Middleware Libraries, HAL Multimedia Audio, Video, Images NDK / Middleware / HAL OS Concepts PHP Programming Languages Scripting and Automation Search Engine Optimisation ( SEO ) Social Media Source Code Management ( SCM ) System Administration, Security Testing and Debugging Uncategorized Web design and development Website Hosting Wordpress Yocto / Bitbake / Openembedded