HTML Forms and LSP for Beginners

This tutorial introduces the concept of server side generated content aka server side scripting.

Ref Wikipedia: Server-side scripting
A program running on a web server (server-side scripting) is used to change the web content on various web pages or to adjust the sequence of or reload of the web pages. Server responses may be determined by such conditions as data in a posted HTML form, parameters in the URL, the type of browser being used, the passage of time, or a database or server state.

In this tutorial, we will look into the basics of LSP and how you can use HTML forms for sending data from the browser to the server.  When we convert simple HTML pages into interactive applications we need to get user input to be processed at the server side. The server side processing is done by Lua Server Pages (LSP) in the Mako Server.

How LSP Works

Let's take a quick look at the inner working of LSP before moving onto designing HTML web forms.  Having a basic understanding of the LSP engine will make it easier for you to design server side web applications. LSP can dynamically create any type of text so let's make it simple by creating an LSP page that returns "Hello World".

An LSP page containing the two words "Hello World" will be converted by the LSP processor into Lua code similar to the following:

function action()
   response:write("Hello World")
end

Figure 1 illustrates how an LSP "Hello World" page is converted to Lua. Note, this example is for illustration purposes only and should not be used.

The Lua function action() is called by the Mako Server runtime engine when a browser visits our hello world LSP page. The action() function's environment (aka scope) includes a number of pre-defined variables such as the request object and the response object. The request object makes it easy to retrieve information provided by the client and the response object is used when sending response data back to the client.

The above example is not very exciting since the produced result is no different from a static HTML page. We have to use LSP tags in order to create dynamic content.

compileLSP

Figure 1. Recompiling LSP is as simple as refreshing the browser window.

LSP provides a simple and fast way of creating dynamic web pages. Lua script can be freely intermixed with text such as HTML and XML. LSP tags are XML compliant <?lsp    ?>. Code between these tags is executed as Lua code. Expressions are provided by the <?lsp=    ?> tag. The result of an expression is emitted as HTML/XML.

We can insert Lua code into an LSP page by using LSP code tags and LSP expression tags. The following example dynamically creates a response message from the HTTP method used by the client:

LSP page:

<?lsp if request:method() == "GET" then ?>
   You sent a GET request
<?lsp else ?>
   You sent a <?lsp=request:method()?> request
<?lsp end ?>

Figure 2 shows how to dynamically produce HTML responses from the HTTP method type.

Processed LSP page:

function action()
   if request:method() == "GET" then
      response:write("You sent a GET request")
   else
      response:write("You sent a ",request:method()," request")
   end
end

Figure 3 illustrates how the LSP in Figure 2 is converted to Lua. Note, this example is for illustration purposes only and should not be used.

The LSP processing is automatic and you will not see the processed LSP page as shown above. The complete processing and compilation sequence is shown in figure 1, where the LSP processor converts LSP to Lua, and the Lua compiler compiles Lua into byte code that in turn is executed by the Lua runtime engine.

HTML form data and query string (URL-encoding)

HTML forms send data as key/value pairs to the server, where the key/value pairs can be sent as data content just after the initial HTTP header or as part of the URL.

key1=value1&key2=value2&key3=value3

Figure 4 shows how key/value pairs are sent to the server.

A number of characters are reserved and must be escaped. For example, the ampersand character must be escaped since this character is used to separate the key/value pairs. Escaping the characters are known as URL encoding. The encoding/decoding is normally automatic and transparent to you as a developer. The browser automatically encodes the data and the server automatically decodes the data.

The key/value pairs are embedded in the query string when they are sent as part of the URL. The client typically sends a GET request to the server when sending a query string. As an example, clicking the following link sends a GET request with the key 'q' and the value 'URL encoding' as part of the query string to the "let me Google that for you" service.

Having an understanding of the HTTP protocol is not required when using the Mako Server, but if you are curious, you may want to read the online tutorial HTTP Made Really Easy.

http://lmgtfy.com/?q=URL+Encoding

Although one can send form data as a GET request, it is more common to send form data as a POST request and append the URL encoded data just after the HTTP header. A browser sends POST data as "application/x-www-form-urlencoded" to the server.

In Lua, key value pairs are best represented as a table. The method request:data() returns a Lua table with all key/value pairs sent to the server. The following example shows how to iterate and print all URL encoded data sent from the client to the server. The following example shows how to iterate and print all URL encoded data sent from the client to the server. The data printed is sent as a response back to the HTTP client that performed the request.

<?lsp
for key,value in pairs(request:data()) do
   response:write("key=", key, ", value=", value, "<br>")
end
?>

Figure 5 shows how to iterate and print out all key/value pairs received from the client.

You can save the above example in an LSP page, run the Mako Server, and enter the key/value pairs in the browser as follows:

http://server-name/page-name.lsp?key1=value1&key2=value2&key3=value3

The returned page should look like the following:

key=key1, value=value1
key=key2, value=value2
key=key3, value=value3

HTML Forms

A form may contain many different types of input elements that allow the user to enter and send information to the server. The input element types you can use in a form are: text fields, text area, drop-downs, radio buttons, check boxes, etc.. They are combined together inside <form> and </form> tags. The values of all the input elements are submitted to the server-side when the user clicks a submit button. As an example, the following HTML illustrates how one could design a basic login form.

<form method="post">
  <input type = "text" name="username">
  <input type = "submit" value="Login">
</form>

You can save the above example in an LSP page and run the example in the Mako Server. Although the example is not a complete HTML page with all required HTML tags such as the body tag, etc., the example will still run in your browser. You can also press the submit button and the browser will send this as a POST request to the server. 

LSP makes it easy to include HTML and process data sent from the browser inside the same LSP page. The first browser request is typically sent as a HTTP GET request and the HTML form data is typically sent as a HTTP POST request when the user clicks the submit button.

The image to the right shows a typical GET – POST sequence.

get-post

If you try the above example in the Mako Server, you’ll notice that nothing happens when you press the submit button. The form is sent as POST data from the browser to the server, but the above LSP page includes no server side logic that manages the submitted data. Let’s go ahead and add some basic Lua code that manages the submitted data.

01: <?lsp
02: local username
03: local session = request:session()
04: local data=request:data()
05: if request:method() == "POST" then
06:    if data.username then
07:       username=data.username
08:       request:session(true).username=username
09:    elseif session then
10:       session:terminate()
11:    end
12: else
13:    username = session and session.username
14: end
15: ?>
16: 
17: <form method="post">
18:    <?lsp if username then ?>
19:       <h1>Hello <?lsp=username?></h1>
20:       <input type = "submit" value="Logout">
21:    <?lsp else ?>
22:       <input type = "text" name="username">
23:       <input type = "submit" value="Login">
24:    <?lsp end ?>
25: </form>

If you look at the above example, you will notice that in addition to the new server side logic at the top, we have also changed how the server dynamically creates the form. Line 17 to 25 dynamically creates a HTML login form or a HTML logout form. The login form is dynamically created if the variable username is nil. The logout form is dynamically created if the variable username is not nil.

We fetch the session object on line 3. Method request:session() returns nil if we do not have a session, which is the case when we are not logged in.

We fetch the submitted data on line 4. Method request:data() returns a Lua table with all the submitted key/value pairs sent from the browser when the submit button was pressed. The table will be empty if no data was submitted.

We check if this is a HTML form submit on line 5 -- i.e. if this is a HTTP POST. The browser will not send a POST request unless you press the submit button. The first time you load the page or if you press the refresh button you will end up on line 13. The code on line 13 retrieves the username if we have a session -- i.e., if the user is logged in.

We check if the submitted data contains "username" on line 6. This is only true if the user submits the data in the login form since only the login form includes an "input" (line 22) whose name is "username".  If the login button is pressed, the username is permanently stored in the session object created on line 8.

If the logout button is pressed, line 6 evaluates to false and we end up on line 10.

The following two images show our basic login page in action.

image image

Testing the HTML Form Example

Please note that the Mako Server includes advanced authentication and authorization management APIs and you would normally not create a login page as shown in the above example.

  1. Download and install the Mako Server
  2. Create a directory such as "test"
  3. Start the Mako Server as follows: mako -l::test
  4. Download the above form example
  5. Save the form example in your "test" directory
  6. Use a browser and navigate to http://localhost/form.lsp, where localhost is the name of the computer running your Mako Server.

Posted in Tutorials by bd