Lua JSON Web Services

JSON Web Services or JSON RPC is based on the JSON-RPC 1.1 Specification. JSON is a very compact data-interchange format and uses up to 4 times less bandwidth than XML based protocols such as SOAP.

Our JSON RPC implementation makes it extremely easy to export Lua functions in the server as Web Services, which can be called by any compliant JSON RPC client. We also provide a JSON-RPC client JavaScript library that can be used by WEB 2.0 applications loaded into a browser.

Exporting Lua functions

The Barracuda Embedded Web Server can provide an unlimited number of JSON RPC services. A JSON RPC service can be installed at any URL location in the server. Any LSP page can be used as an entry point for JSON RPC, but you must not generate any content in the page. The JSON RPC object automatically generates the required response.

<?lsp -- Lua RPC code here. You must not have anything outside <? And ?> ?>

A JSON RPC service in Barracuda consists of one or several objects. Each object in turn consists of one or several methods. This is equivalent to an object oriented design where one typically calls a method in an object, example: math.subtract(10,5)

As an example, assume we want a math JSON service. The math service provides a math object and methods such as add, subtract, etc..

<?lsp -- (1) Load the JSON RPC service local jsonrpc=require"json.rpc" -- (2) Our math.add Web-Services function function add(a,b) return a + b end -- Our math.subtract Web-Services function function subtract(a,b) return a - b end -- (3) Create the math web service local mathService = json.Rpc.new("A basic math service", { math={ -- (4) The math Web-Services object add=subtract, subtract=subtract, } }) -- (5) Execute the web service mathService:execute(request, response) ?>

(1) Load the JSON RPC service

The first thing we must do is to load the json.rpc code. The json.rpc code, which is implemented in Lua, is integrated into BarracudaDrive. You must make sure you have this code available to the VM if you are not using BarracudaDrive i.e. if you are using the Barracuda SDK.

(2) Web-Services functions

Web services functions are standard Lua functions. The JSON RPC library automatically decodes the JSON arguments sent from the client. One can have any number of arguments, and the argument can be of any type.

One can also have dynamic number of arguments. For example, we can change the add function to work with any number of arguments. The following example returns the summation of all its arguments:

function add(...) local s = 0 for i, v in ipairs{...} do s = s + v end return s end

We are not doing any type checking on the arguments in (2). The Lua VM may throw an exception if the two arguments cannot be added.

You can add argument validation to the code as follows:
function add(a,b) if type(a) ~= "number" then error("The first argument is not a number") end if type(b) ~= "number" then error("The second argument is not a number") end return a + b end

Function "error" generates an exception and the exception message is sent back to the client. Exceptions are thrown all the way back to the client. For example, our JSON-RPC JavaScript library throws an exception if calling a server side function fails. See the JSON-RPC JavaScript library for more information.

(3) Create the math web service

We now create a JSON RPC object by calling json.Rpc.new. The function takes two arguments, a string and a table. The string is sent to the client if the client library implements introspection. The table is where we declare the web services.

(4) The math Web-Services object

The table must contain at least one sub-table. We mentioned above that a JSON RPC service in Barracuda consists of one or several objects, where each object in turn consists of one or several methods. This is not an option; you cannot just export the function(s). We have only one object, the math object. The math table contains two functions, add and subtract. A client can now call math.add and math.subtract.

(5) Execute the Web-Service

We have so far just declared the functions and created the JSON-RPC object "mathService". We must now execute the Web-Service. We do this by calling the execute method. The execut method takes two arguments, the request object, and the response object. The request object is used by the JSON-RPC object for reading data sent from the client. This data is decoded, the correct Web-Services function is located, and called. The response object is used when either sending response data or if sending exceptions. The client JSON implementation will freak out if you generate any response data outside of the <? and ?>.

Optimizing the JSON Web-Services

You may have noticed that we created a JSON-RPC object (3) every time the client calls one of our Web-Services functions. This is great during development as the LSP compiler recompiles the LSP page automatically if the page has changed. You can optimize the code when you have completed the development by moving all code, except for (5) to the application object. The application object is created when your LSP application starts. The VM executes the .preload script, if found, when you load an LSP application. You can simply move the code into this file when you are done with the development. The LSP script will then only contain one line of code.

<?lsp app.mathService:execute(request, response) ?>

Notice that we must now reference the mathService object via the application object.