In this blogpost, we are going to show you how easy it is to implement a RESTful client with Mongoose. As always, the full source code of this example is available on Github. All you need to do is to clone the repo and type “make” in the example directory.

How the RESTful client example works

When the example is built, it produces a binary executable file which can be started from the shell:

$ ./restful_client
Starting RESTful client against
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=cesanta
Got reply:
{"responseData": null, "responseDetails": "The Google Web Search API is no longer available. Please migrate to the Google Custom Search API (https://developers.google.com/custom-search/)", "responseStatus": 403}

As you can see, the binary fires a RESTful request, hardcoded against one of the Google online services and prints the reply to the terminal.

On to investigating the code.

Code explained

This is the standard boilerplate to initialise the event manager and create an outbound connection:

mg_mgr_init(&mgr, NULL);
nc = mg_connect_http(&mgr, ev_handler, s_url, NULL, NULL);
mg_set_protocol_http_websocket(nc);

Then this is the infinite event loop:

printf("Starting RESTful client against %s\n", s_url);
while (s_exit_flag == 0) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);

And now the core; an event handler function. What does it need to do? First, catch the MG_EV_CONNECT event to see whether the connection to the server was successful. If it wasn’t it will print an error and stop event loop.

Then, we handle the MG_EV_HTTP_REPLY event by printing the whole HTTP body received to the terminal. Here’s the code:

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct http_message *hm = (struct http_message *) ev_data;
int connect_status;
switch (ev) {
case MG_EV_CONNECT:
connect_status = *(int *) ev_data;
if (connect_status != 0) {
printf("Error connecting to %s: %s\n", s_url,
strerror(connect_status));
s_exit_flag = 1;
}
break;
case MG_EV_HTTP_REPLY:
printf("Got reply:\n%.*s\n", (int) hm->body.len, hm->body.p);
nc->flags |= MG_F_SEND_AND_CLOSE;
s_exit_flag = 1;
break;
default:
break;
}
}

When the HTTP payload printed, we also stop the event loop and exit the program.

We hope you enjoy recreating this example!

To contact: send us a message or ask on the developer forum.