Tutorial

The following sections will guide you through some examples, which provide enough knowledge to get a web application up and running as quickly as possible.

The only prerequisite for this tutorial is a basic knowledge of C and HTML.

An overview of the functionality is provided through examples. For more detail on functions and parameters please refer to the KLone API.

Bootstrap

Create an empty directory and edit a new bootstrap Makefile inside it (or simply download a ready-made version):

KLONE_VERSION ?= 3.1.0

# webapp content is in webapp/ the current dir
WEBAPP_DIR = $(CURDIR)/webapp

include klapp.mk

klapp.mk: ; wget -O $@ -c http://koanlogic.com/klone/klapp.mk

The default fetch command is wget, but you can override it with FETCH_CMD = curl for example.

Now run make (GNU make must be used).

The framework will download KLone, compile it and create a simple Hello World application ready to be customized.

Let's run the daemon to see KLone in action:

$ ./kloned

Connect to the running webapp with your browser: http://localhost:8080/

This is what the page should look like:

Hello World!

Add a new page

Now let's try to add a new web page.

During the bootstrap procedure the framework creates the webapp directory that holds the content of a basic web application starting from a template.

Everything found in the webapp directory is automatically compiled, bundled into the KLone daemon executable and made available to the clients through HTTP.

So to add a new page we have to create a new file in the webapp directory and run make again (the same applies to file removal and modifications).

Create the file: webapp/www/first.html

<html>
<head>
    <title>My first page</title>
    <link rel="stylesheet" href="kl.css" type="text/css">
</head>
<body>

    Hello world!

</body>
</html>

Kill the server if running (killall kloned), rebuild the daemon (make) and restart it (./kloned).

The new page can now be found at http://localhost:8080/first.html .

Dynamic content

To make a web application useful we need to bring some dynamic content into it. As an example we will build a basic directory browser.

The first page (root.kl1) displays the content of the root directory of the computer running the KLone server.

<%!
    #include <string.h>
    #include <sys/types.h>
    #include <dirent.h>
%>

<html>
<head>
    <title>My first page</title>
    <link rel="stylesheet" href="kl.css" type="text/css">
</head>
<body>

<h3>Root dir content:</h3>
<ul>
<%
    DIR *dirp;
    struct dirent *dp;

    dirp = opendir("/");
    while ((dp = readdir(dirp)) != NULL)
        io_printf(out, "<li>%s</li>", dp->d_name);
    closedir(dirp);
%>
    
</ul>

</body>
</html>

The output will be the list of files and directories on your computer.

As you can see there are two blocks of C code enclosed in two different kinds of KLone blocks:

You may think of the page as a big function with lots of printf()s that print the HTML code.
All <%   %> blocks go inside such a function while <%!    %> blocks go outside the scope of this function.

Another important thing to notice is the io_printf(out, ...) line.

This is the function to be used to print data to the output stream. You can use the same arguments used for the standard printf() function, just prepend all arguments with 'out' (which is a global variable defined within KLone):


io_printf(out, "%s", "this is a string");

io_printf(out, "I'm %d years old", 21);

const char *text = "hello!";

io_printf(out, "text: %s", text);

Using functions

Back to our demo.

The root.kl1 file displays the root directory of the system but does not help for browsing directories. The following script (ls.kl1) adds the necessary code to allow users to browser our disk (error checks not included for brevity/clarity). The result is a page showing a list of files and a clickable list of directories.

<%!
    #include <string.h>
    #include <sys/types.h>
    #include <dirent.h>

    void print_item(const char *curdir, struct dirent *dp)
    {
        if(dp->d_type == DT_DIR)
            io_printf(out, 
                    "<li> <a href=\"%s?dir=%s/%s\"> %s </a> </li>", 
                    SCRIPT_NAME, curdir, dp->d_name, dp->d_name);
        else
            io_printf(out, "<li>%s</li>", dp->d_name);
    }
%>

<html>
<head>
    <title>Klone tutorial</title>
    <link rel="stylesheet" href="kl.css" type="text/css">
</head>
<body>

<h3>Dir contents:</h3>
<ul>
<%
    DIR *dirp;
    struct dirent *dp;
    char *curdir; /* directory to display */

    if((curdir = request_get_arg(request, "dir")) == NULL)
        curdir = "/"; 

    dirp = opendir(curdir);
    while ((dp = readdir(dirp)) != NULL)
        print_item(curdir, dp);

    closedir(dirp);
%>
    
</ul>

</body>
</html>

There are two important things to notice: the first is that the code to print the filename or the directory link has been moved into the print_item() function as a declaration block (<%! %>).

The second and most important thing to notice is the request_get_arg() function call. This is one of KLone functions that let you extract user passed variables.

If a user submits an HTML FORM with two INPUT text fields named Height and Weight to a KLone script you can read the values provided by the user with:

const char *height, *weight;

height = request_get_arg(request, "Height");
weight = request_get_arg(request, "Weight");

Just like the 'out' variable seen above, 'request' is a global variable predefined by KLone.

The complete list of predefined variables follows:

Configuration options

The KLone configuration file is embedded into the executable file during compilation just like any other content. This allows the kloned daemon to run on systems without a file system.

To modify the KLone configuration you will need to edit the kloned.conf file in the webapp/etc/ directory and run 'make' to rebuild the daemon.

Otherwise, if you wish to use a different, external, configuration file you can use the '-f' switch of the kloned daemon:

$ ./kloned -f /etc/mywebapp.conf

Warning!

It's probably time to shutdown the demo to avoid displaying the content of your disk to the whole world :-)