MONGOOSE HTTP EXAMPLES

HTTP Client Example

 

Mongoose Version 6.0 was a big milestone for our embedded web server. Since 6.0, Mongoose is not longer just a web server - it is a multi-protocol networking library, a Swiss army knife of embedded networking development. 

 

This is a simple example: a HTTP client. Yes, you can now make HTTP requests as well as serve them. The client is asynchronous and uses the same event handling paradigm. Take a look:

mg_mgr_init(&mgr, NULL);  
mg_connect_http
(&mgr, ev_handler, "http://www.example.org/", NULL, NULL);

When the request is finished, event handler will receive MG_EV_HTTP_REPLY:

void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  struct http_message *hm = (struct http_message *) ev_data;

  switch (ev) {
    ...
    case MG_EV_HTTP_REPLY:
      /* Check hm->resp_code, do something with hm->body. */
      break;
    ...
  }
}

 

  Download Mongoose Embedded Web Server HTTP Client Example Code

 

HTTP Load Balancer Example

 

This is a fairly advanced example that will showcase Mongoose usage as both a server and a client. You can download Mongoose Embedded Web Server and work through the example yourself.

 

HTTP load balancer is a piece of serving infrastructure; an additional stage between a user’s browser and a server that is introduced when there are multiple servers to choose from. Which one should be used to handle client’s request? Load balancer takes the user’s request, makes the decision and forwards it to one of the servers. These are commonly called backends. More advanced load balancers will keep track of the load of the backends and pick the least loaded, but our example load balancer is very basic: it will just alternate between the configured backends. We have two backends configured, the first request will go to backend 1, the second will go to backend 2, the third will go to backend 1 again and so forth.

 

Example run-through

 

So let’s test it first and then look take a look under the hood. For our example we will need the balancer itself and backends. We will use a restful server as the backend. We’ll need at least two to see balancing going on, so let’s compile and start two on different ports:

mongoose/examples/restful_server$ make
cc restful_server.c ../../mongoose.c -o restful_server -g -W -Wall -I../.. -Wno-unused-function  -DMG_ENABLE_THREADS -DMG_DISABLE_HTTP_WEBSOCKET -lpthread
mongoose/examples/restful_server$ ./restful_server -p 8910
Starting RESTful server on port 8910, serving .

In another terminal window - ran simultaneously:

mongoose/examples/restful_server$ ./restful_server -p 8911
Starting RESTful server on port 8910, serving .

Use your browser to verify that both backends are working: http://127.0.0.1:8910 and http://127.0.0.1:8911 should display the “RESTful API demo” index page.

 

Now compile and run the load_balancer example:

mongoose/examples/load_balancer master$ make
cc load_balancer.c ../../mongoose.c -o load_balancer -W -Wall -pthread
rojer@nbt:~/go/src/cesanta.com/mongoose/examples/load_balancer master$ ./load_balancer -p 8000 -l - -b / 127.0.0.1:8910 -b / 127.0.0.1:8911
Adding backend for / : 127.0.0.1:8910 [redirect=0,prefix_replacement=/]
Adding backend for / : 127.0.0.1:8911 [redirect=0,prefix_replacement=/]
Starting LB on port 8000

Arguments are documented in the README file, but briefly: -p 8000 tells it to listen for incoming connection on port 8000, -l - sets the log file to “-”, which is a special value for stdout and the two -b options add our backends.

 

With that done, you should see the same index page when you point your browser to http://127.0.0.1:8000/. But, each time you reload, the page will be served by a different instance of the backend, and you will see records in the balancer log:

1465822060 GET / backend=127.0.0.1:8910
1465822061 GET / backend=127.0.0.1:8911
1465822062 GET / backend=127.0.0.1:8910

Under the hood

 

Now, let’s check out how it works internally. There are a few hundred lines of code in the main file, but as usual, most of the action happens in the event handler (ev_handler). When the client’s request arrives (ev == MG_EV_HTTP_REQUEST), it picks a backend to use, connects to it and forwards the client’s request. When the server responds (ev == MG_EV_HTTP_REPLY), the response is forwarded to the client’s connection. The rest of the code is error handling, dealing with HTTP keep-alive and idle backends.

 

That’s it for now, we hope this helps you get an idea of how to combine serving and making HTTP requests in the same program.

 

Download Mongoose Embedded Web Server HTTP Load Balancer Example Code

Contact Us
Have questions about Cesanta, our licensing, support services or anything else? Let us know and we'll get back to you.
GET IN TOUCH