Add example of REST client
by using libcurl for HTTP connection and M*LIB for JSON formating.
This commit is contained in:
1 parent
b16048a55b
commit
0c8eca893d
2 files changed
+164
-4
No files matched your search
+4
-4
@@ -31,7 +31,7 @@ RM=rm -f
|
||||
.SUFFIXES: .c .exe
|
||||
|
||||
.c.exe:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ `cat config` $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ `cat config` `cat config.curl` $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
@$(MAKE) config
|
||||
@@ -53,11 +53,11 @@ config:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(GMP_DIR)/include -L$(GMP_DIR)/lib config-test.c -lgmp -o config-test.exe $(LDFLAGS) 2> /dev/null && echo "-DHAVE_GMP=1 -DHAVE_MPFR=0 -I$(GMP_DIR)/include -L$(GMP_DIR)/lib -lgmp" > config || echo "-DHAVE_GMP=0 -DHAVE_MPFR=0 " > config
|
||||
printf "#include <mpfr.h>\nint main(void){mpfr_t z; mpfr_init(z); return 0;}\n" > config-test.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(GMP_DIR)/include -I$(MPFR_DIR)/include -L$(GMP_DIR)/lib -L$(MPFR_DIR)/lib config-test.c -lmpfr -lgmp -o config-test.exe $(LDFLAGS) 2> /dev/null && echo "-DHAVE_GMP=1 -DHAVE_MPFR=1 -I$(GMP_DIR)/include -L$(GMP_DIR)/lib -I$(MPFR_DIR)/include -L$(MPFR_DIR)/lib -lmpfr -lgmp" > config || echo "MPFR not available"
|
||||
printf "#include <curl/curl.h>\nint main(void){curl_global_init(CURL_GLOBAL_DEFAULT);}" > config-test.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) config-test.c `curl-config --cflags --libs` -o config-test.exe 2> /dev/null && echo "-DHAVE_CURL=1 `curl-config --cflags --libs`" > config.curl || echo "-DHAVE_CURL=0 " > config.curl
|
||||
printf "#include <stdio.h>\nint main(void){printf(\"Ok\"); return 0;}\n" > config-test.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) config-test.c -ffunction-sections -fdata-sections -Wl,--gc-sections 2> /dev/null && echo "-ffunction-sections -fdata-sections -Wl,--gc-sections" > config.link || echo "" > config.link
|
||||
$(RM) config-test.c config-test.exe
|
||||
|
||||
clean:
|
||||
$(RM) *.exe *.s *~ *.o ./a.dat config config.link
|
||||
|
||||
|
||||
$(RM) *.exe *.s *~ *.o ./a.dat config config.link config.curl
|
||||
@@ -0,0 +1,160 @@
|
||||
#if HAVE_CURL
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "m-dict.h"
|
||||
#include "m-tuple.h"
|
||||
#include "m-string.h"
|
||||
#include "m-list.h"
|
||||
#include "m-serial-json.h"
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
// Define container types
|
||||
// First a generic map string to string
|
||||
DICT_DEF2(map_str, string_t, string_t)
|
||||
#define M_OPL_map_str_t() DICT_OPLIST(map_str, STRING_OPLIST, STRING_OPLIST)
|
||||
|
||||
// This structure matches the JSON structure returns by the used WEB server
|
||||
// for the GET command.
|
||||
// It can be whatever you want provided it matches what is expected by the WEB server
|
||||
TUPLE_DEF2(web_data,
|
||||
(args, map_str_t),
|
||||
(headers, map_str_t),
|
||||
(origin, string_t),
|
||||
(url, string_t))
|
||||
#define M_OPL_web_data_t() TUPLE_OPLIST(web_data, M_OPL_map_str_t(), M_OPL_map_str_t(), STRING_T, STRING_T)
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
static size_t
|
||||
write_data(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
(void) size; // Parameter not used
|
||||
char *src = buffer;
|
||||
string_ptr str = userp;
|
||||
for(size_t i = 0; i < nmemb; i++) {
|
||||
string_push_back(str, src[i]);
|
||||
}
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
static bool get_data(web_data_t data, const char url[])
|
||||
{
|
||||
m_serial_return_code_t r = M_SERIAL_FAIL;
|
||||
CURLcode res;
|
||||
string_t str;
|
||||
CURL *handle = curl_easy_init();
|
||||
if (handle) {
|
||||
string_init(str);
|
||||
// Perform an http GET request and fill in str with the JSON answer
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, str);
|
||||
res = curl_easy_perform(handle);
|
||||
curl_easy_cleanup(handle);
|
||||
if (res == CURLE_OK) {
|
||||
// Parse the string and fill in the object
|
||||
m_serial_str_json_read_t serial;
|
||||
m_serial_str_json_read_init(serial, string_get_cstr(str));
|
||||
r = web_data_in_serial(data, serial);
|
||||
m_serial_str_json_read_clear(serial);
|
||||
}
|
||||
string_clear(str);
|
||||
}
|
||||
return r == M_SERIAL_OK_DONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
static size_t
|
||||
ignore_data(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
(void) buffer; // Parameter not used
|
||||
(void) size; // Parameter not used
|
||||
(void) userp; // Parameter not used
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
static bool post_data(web_data_t data, const char url[], bool display_answer)
|
||||
{
|
||||
m_serial_return_code_t r = M_SERIAL_FAIL;
|
||||
CURLcode res = 0;
|
||||
string_t str;
|
||||
CURL *handle = curl_easy_init();
|
||||
if (handle) {
|
||||
string_init(str);
|
||||
// Get a JSON string
|
||||
m_serial_str_json_write_t serial;
|
||||
m_serial_str_json_write_init(serial, str);
|
||||
r = web_data_out_serial(serial, data);
|
||||
m_serial_str_json_write_clear(serial);
|
||||
if (r == M_SERIAL_OK_DONE) {
|
||||
// Post JSON string
|
||||
struct curl_slist *headers=NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type: text/json");
|
||||
if (headers != NULL) {
|
||||
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, string_get_cstr(str));
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url);
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
|
||||
if (display_answer == false) {
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ignore_data);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL);
|
||||
}
|
||||
res = curl_easy_perform(handle);
|
||||
curl_slist_free_all(headers);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(handle);
|
||||
string_clear(str);
|
||||
}
|
||||
return (r == M_SERIAL_OK_DONE) && (res == CURLE_OK);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
// Remote server URL
|
||||
#define URL_GET "https://httpbin.org/get"
|
||||
#define URL_POST "https://httpbin.org/post"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURLcode ret = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (ret != CURLE_OK) abort();
|
||||
|
||||
web_data_t data;
|
||||
web_data_init(data);
|
||||
|
||||
// Test http GET
|
||||
bool b = get_data(data, URL_GET);
|
||||
if (b) {
|
||||
// We success receiving the JSON object and fill in the C object web_data with it.
|
||||
// Let's display the object content:
|
||||
printf("SUCCESS. Receive data =\n");
|
||||
web_data_out_str(stdout, data);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("ERROR: Cannot GET data or get data are not in expected format\n");
|
||||
}
|
||||
|
||||
// Test http POST
|
||||
web_data_emplace_origin(data, "This is the origin");
|
||||
web_data_emplace_url(data, "This is the URL");
|
||||
//web_data_set_origin(data, STRING_CTE("This is the origin"));
|
||||
//web_data_set_url(data, STRING_CTE("This is the URL"));
|
||||
b = post_data(data, URL_POST, false);
|
||||
if (b) {
|
||||
printf("SUCCESS: Post\n");
|
||||
} else {
|
||||
printf("ERROR post\n");
|
||||
}
|
||||
|
||||
web_data_clear(data);
|
||||
|
||||
curl_global_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int main(void) { return 0; }
|
||||
#endif
|
||||
Reference in new issue
Block a user