HTTP Client

Overview

This tutorial will show you how to implement an HTTP client using Mongoose Library.

Build and run

Follow the Build Tools tutorial to setup your development environment. Then start a command prompt / terminal and enter the following:

git clone https://github.com/cesanta/mongoose
cd mongoose/tutorials/http/http-client
make

Done! The full source code for this tutorial is at https://github.com/cesanta/mongoose/tree/master/tutorials/http/http-client

By default, the http-client example connects to http://info.cern.ch/ - the very first web server on the planet. You can use any other URL: make ARGS=http://my-site.com. If your URL is HTTPS, then make sure to build this example with TLS support - see below.

A basic HTTP client

Let's start with a minimal Mongoose template that initialises and starts an event manager, but does nothing:

#include "mongoose.h"

int main(int argc, char *argv[]) {
  struct mg_mgr mgr;
  mg_mgr_init(&mgr);                  // Init manager
  for (;;) mg_mgr_poll(&mgr, 1000);   // Event loop
  mg_mgr_free(&mgr);                  // Cleanup
  return 0;
}

Now, let's create an HTTP client connection before the event loop starts. We will fetch the very first web page in history - a page from CERN, where the Web was invented by Tim Bernes-Lee. That web page is still alive! Let's create a variable that holds a URL:

  // First web page in history
  static const char *s_url = "http://info.cern.ch/";  

Client connection

Now, add a client connection. We need an event handler function for it. That event handler function is going to get an MG_EV_HTTP_MSG event when a full page content gets downloaded.

A client connection is created by the mg_http_connect() function. An important aspect of that function is that it only creates a TCP connection to the server, but does not send a request. The reason for this is that an HTTP request could be quite complex; therefore it is our responsibility to construct the request. We do it when we receive an MG_EV_CONNECT event.

There, we extract a hostname from the URL to form a valid Host header, which is mandatory for HTTP/1.1, using the mg_url_host() function. We also make use of the mg_url_uri() function to point to the URI part in the URL.

Finally, we send a simple GET request using mg_printf():

#include "mongoose.h"

// First web page in history
static const char *s_url = "http://info.cern.ch/";  

static void fn(struct mg_connection *c, int ev, void *ev_data) {
  if (ev == MG_EV_CONNECT) {
    struct mg_str host = mg_url_host(s_url);
    // Send request
    mg_printf(c,
              "GET %s HTTP/1.0\r\n"
              "Host: %.*s\r\n"
              "\r\n",
              mg_url_uri(s_url), (int) host.len, host.buf);
  } if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    printf("%.*s", (int) hm->message.len, hm->message.buf);
  }
}

int main(int argc, char *argv[]) {
  struct mg_mgr mgr;
  mg_mgr_init(&mgr);                        // Init manager
  mg_http_connect(&mgr, s_url, fn, NULL);   // Create client connection
  for (;;) mg_mgr_poll(&mgr, 1000);         // Event loop
  mg_mgr_free(&mgr);                        // Cleanup
  return 0;
}

Error handling

Connection failures will trigger an MG_EV_ERROR event; an error reason is passed as a char * pointer in parameter ev_data.

Check the error handling tutorial for more information

Build with TLS support

Check the "How to build" section of the TLS tutorial for specific information on building options for your OS

Now you can pass an HTTPS URL to the compiled example.

For more information on developing TLS clients, check the TLS tutorial