MicroHTTP Library: Using Server Side Includes
On this page I will explain how to create dynamic web content with the MicroHTTP library's SSI capabilities.
Enabling SSI
To enable SSI, the application must register a handler for it. The easiest way to do this is to enable default SSI support in the Configurator. The application simply needs to call
int MediaTypeInitDefaults(void);
to activate all configured handlers. For SSI, it will register the internal default handler
int HttpSsiHandler(HTTPD_SESSION *hs, const MEDIA_TYPE_ENTRY *mt, const char *ext);
When the browser requests a file with extension shtml, the web server will redirect the request to the SSI handler. The handler parses the file for SSI elements and replaces them according to the SSI syntax rules.
At the time of this writing, the following SSI elements are recognized by the server:
- echo to include the value of a variable.
- exec to execute a CGI script and include its output.
- include to include the contents of an external file.
Support for if-then-else is not provided, probably the most missing feature. If implemented once, we would also miss the set command.
CGI scripts had been discussed on the previous page. Including external files is straight forward and a simple way to add common parts like menus to all your webpages. Retrieving the value of variables will be explained now.
Predefined Variables
The library offers a number of predefined SSI variables, for example the current date and time. The following HTTP snippet displays the local time as well as the Greenwich Mean Time.
<p>Local time <!--#echo var="DATE_LOCAL" --></p> <p>GMT time <!--#echo var="DATE_GMT" --></p>
To enable these variables, applications must call
int EnvInitDefaults(void); HTTP_SSI_VARHANDLER HttpRegisterSsiVarHandler(HTTP_SSI_VARHANDLER handler);
The first call adds all predefined variables to the environment and the second call is used to register a handler. MicroHTTP offers a default handler named EnvHandler, which can be registered with
HttpRegisterSsiVarHandler(EnvHandler);
The library supports the following variables:
- SERVER_PORT
- SERVER_NAME
- SERVER_ADDR
- SCRIPT_NAME
- SCRIPT_FILENAME
- REQUEST_URI
- REQUEST_METHOD
- REMOTE_PORT
- REMOTE_ADDR
- QUERY_STRING_UNESCAPED
- QUERY_STRING
- HTTP_USER_AGENT
- HTTP_REFERER
- HTTP_HOST
- HTTP_COOKIE
- HTTP_CONNECTION
- HTTP_ACCEPT_ENCODING
- DOCUMENT_ROOT
- DOCUMENT_NAME
- DATE_LOCAL
- DATE_GMT
User Defined Variables
The following HTML snippet should display the application's name and version:
<p><!--#echo var="APPNAME" --> <!--#echo var="APPVERSION" --></p>
The default SSI variable handler, that was used for our predefined variables above, also allows to add user defined variables with
int EnvRegisterVariable(char *name, HTTP_ENVVAR_HANDLER handler, int item);
- name points to the name of the variable.
- handler points to the handler for this variable.
- item is an index starting from 1. It will be passed to the handler.
Here is the complete initialization part:
#define APPVAR_NAME 1 #define APPVAR_VERSION 2 StreamInit(); MediaTypeInitDefaults(); EnvRegisterVariable("APPNAME", AppVarHandler, APPVAR_NAME); EnvRegisterVariable("APPVERSION", AppVarHandler, APPVAR_VERSION); HttpRegisterSsiVarHandler(EnvHandler); StreamClientAccept(HttpdClientHandler, NULL);
We can create a single handler for all our user defined variables:
const char *AppVarHandler(HTTPD_SESSION *hs, int item) { static char value[128]; value[0] = '\0'; switch (item) { case APPVAR_NAME: strcpy(value, "SSI Sample"); break; case APPVAR_VERSION: sprintf(value, "%d.%d", MAJOR_VERSION, MINOR_VERSION); break; } return value; }
Note, that the application must make sure, that each variable, which is sharing the same handler, must have a unique index.
Next Step
CGIs and server side includes are most useful to create a web interface to remotely configure your embedded device. Probably, you do not want to grant access to everyone and need some kind of authentication.