Overview

This tutorial will show you the basics of how to implement and use a REST-based user interface (UI).

We'll concentrate here on the basics of a UI based on a RESTful API, for the details on initializing and setting up an HTTP server, parsing, headers, and more details on the API, please check the HTTP server tutorial.

Build and try

  • If you've not already done so, clone the Mongoose Library repo

    $ git clone https://github.com/cesanta/mongoose
    
  • Build and run the example

    $ cd mongoose/examples/webui-rest
    $ make clean all
    
  • Go to http://localhost:8000 in your browser

    • Click on "Call F1", see the results in the log
    • Click on "Call SUM(1,2)", see the results in the log

browser

  • The button on the left sends an HTTP request using the GET method to the URI /api/f1 and shows the results, we can simulate that manually by connecting to the REST API with curl, for example:

    $ curl localhost:8000/api/f1
    {"result": 123}
    
  • The button on the right sends an HTTP request using the POST method to the URI /api/sum, containing a JSON array [1, 2] in the BODY; then shows the results. We can simulate that manually by connecting to the REST API with curl, for example:

    $ curl localhost:8000/api/sum -d '[123, 456]'
    {"result":579}
    

Backend implementation

  • When we get an HTTP request, we must gather more information about it. First, we cast the function argument ev_data to a struct mg_http_message, which contains a parsed HTTP request. Then, we check the URI by calling mg_http_match_uri().

  • If the HTTP request is for the /api/f1 URI, we serve a response using mg_http_reply(), that allows us to generate responses with specific headers and body. It simply prints data to the connection's output buffer according to a printf()-like format specification; it is a convenient wrapper around the function mg_printf(), that adds a correct status message and a Content-Length header. The identifier Q is used to print double-quoted JSON-escaped strings.

  • If the HTTP request is for the /api/sum URI, we assume that the client has sent us the numbers to add as a JSON array in the POST body: [1, 2]. We fetch them using Mongoose's built-in JSON API, calculate the sum, and respond with a result. The function mg_json_get_num() will parse a JSON string in a struct mg_str, searching for a valid numeric value at the JSON path path. If successful, it will store its value at placeholder v and return true; returning false otherwise. The body element inside the struct mg_http_message we got, is a struct mg_str; so we try to extract both values and if we succeed, we print a result.

Check the JSON-RPC tutorial for a more involved example of handling JSON.

You can also check examples/http-restful-server for an expanded version of this minimal example.

Frontend implementation

The JavaScript code in the browser gets the elements that are present on the page, then enables the buttons.

  • On a "Call F1" button click, the code calls the fetch() method to GET /api/f1, extracts the returned JSON object, turns it into a string and shows it in the log
  • On a "Call SUM(1,2)" button click, the code calls the getsum() function and passes numbers 1 and 2 as parameters, then parses the JSON object returned by getsum(), turns it into a string and shows it in the log.
  • The function getsum() calls the fetch() method to POST to /api/sum sending its arguments in the body as a JSON array; then extracts the JSON object returned by the backend, and returns it.