JavaScript-based Web UI
Overview
This tutorial will show you how to implement a plain JavaScript-based user interface (UI) over a REST-based backend.
We'll concentrate here on the basics of the UI, for the basics of implementing a RESTful API and usage of the underlying Mongoose function calls, please check the REST basics tutorial.
Build and try
Follow the Build Tools tutorial to setup your development environment.
Start a terminal in the project directory; 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/tutorials/webui/webui-plain make clean all
Go to
http://localhost:8000
in your browser; the JavaScript code loads and executes, obtaining a configuration and rendering the page; see the results in the log
- Change any parameter, it will be sent to the backend. You can also re-send any one of the values by clicking its "Update" button. Note that, since we don't have any update mechanism in place, yet, to get any possible configuration changes made by other users, you have to click the "Get configuration" button
The "Get configuration" button sends an HTTP request using the GET method to the URI
/api/config/get
and updates the page, we can simulate that manually by connecting to the REST API with curl, for example:curl http://localhost:8000/api/config/get {"url":"mqtt://broker.hivemq.com","pub":"mg/my_device","sub":"mg/#"}
Changes in an input or clicking on one of the "Update" buttons send an HTTP request using the POST method to the URI
/api/config/set
, containing a JSON object with the changed parameter in the BODY. We can simulate that manually by connecting to the REST API with curl, for example:curl http://localhost:8000/api/config/set -d '{"url":"mqtt://otherbroker.some.where"}'
Let's verify that by requesting the configuration again:
curl http://localhost:8000/api/config/get {"url":"mqtt://otherbroker.some.where","pub":"mg/my_device","sub":"mg/#"}
Backend implementation
- When the event manager is initialized and our server starts up, we create a handy copy of pointers to the configuration values. This will allow us to just change the pointers later on, when we get a config change request
- When we get an HTTP request for the
/api/config/get
URI, we serve a response using mg_http_reply(), taking advantage of the identifier m and, through the macroMG_ESC()
, function mg_print_esc(), to print double-quoted JSON-escaped strings.
- When we get an HTTP request for the
/api/config/set
URI, we parse the JSON object in the POST body for each configuration element. Thebody
element inside thestruct mg_http_message
we got, is astruct mg_str
; we pass this to ourupdate_config()
function. Finally, we just print the required HTTP OK result
- The function mg_json_get_str() will parse a JSON string in a
struct mg_str
, searching for a string value at the JSON pathpath
. If successful, it will return a pointer to it, so we free our former config value and generate a new one.
Check the JSON-RPC tutorial for a more involved example of handling JSON.
Frontend implementation
The JavaScript code in the browser gets the elements that are present on the
page, then tries to get the configuration, calling the fetch()
method to GET /api/config/get
and extracting the returned JSON object. If successful, updates the values and enables the buttons
- Each HTML input and button is configured to call its corresponding update function
- Each update function takes the value present in the input and calls
update()
, that calls thefetch()
method to POST to/api/config/set
sending its arguments in the body as a stringified JSON object