The Iguana Demo

Channel 3: Lookup Web Service

Did you know that Iguana can act as a web service? This is a great leap forward in interface design because it allows anyone to retrieve specific message details via a simple URL.

This demo channel demonstrates just how easy this is to implement:

How It works

The 03-Lookup Web Service demo channel consists of the following components (although in this example, only the source component is in use):

Component Type Function
Source ‘From HTTPS'(script) Acting as the web server, this component will perform the following steps:

  1. ‘Listen’ to a specific URL for incoming requests: http://localhost:6544/lookup
  2. Filter incoming requests for a specific parameter.
  3. Search for the requested parameter in an external database: PatientData.sqlite (Iguana/Demo)
  4. Return the results in either XML or JSON format.
Filter inactive n/a
Destination ‘To Channel’ n/a

Since the ‘From HTTPS’ source component is acting as a web server, it is managing both the incoming and outgoing data. As such, we don’t need any other active components for this channel. However, that doesn’t mean that they aren’t defined:

  • Every channel includes a Filter component. This channel’s filter in inactive as we have chosen to leave it disabled (default).
  • Every channel requires a Destination component. For this channel, we’ve selected the ‘To Channel’ type as it requires no further configuration or overhead.

Understanding the Code

If you are having difficulty understanding this channel’s code, don’t panic. This section explains each line of the script to help you get better oriented.

require 'node'

Our first step is to import all the shared modules that we will need. In this particular instance, we need a module named ‘node’ that will convert a node to a string (and escape any characters that need escaped).

function main(Data)

The main() function is the primary function that Iguana calls when running a script. The rest of your code simply defines the tasks that main() is in charge of executing. In this script, the main() function receives the incoming web requests. Any parameter name will work here, but we chose ‘Data’.

local Request = net.http.parseRequest{data=Data}

We use net.http.parse to receive and parse incoming web requests into their various components (for easier identification). These might include parameters, cookies, location, headers, etc.

if Request.params.LastName then
    local Result, MimeType = PatientSearch(Request.params.LastName, Request.params.format)
    net.http.respond{body=Result, entity_type=MimeType}
    return
end

This conditional statement checks for the ‘LastName’ parameter within each parsed web request. If there is one, then the main line of this statement runs the PatientSearch() function to retreive the corresponding data. Then the script will return the results (‘Result’) using the chosen format (‘MimeType’) .

Note: We define how PatientSearch() works further down in the script.

DB = db.connect{api=db.SQLITE, name='Demo/Database/PatientData.sqlite'}'

Before we can send anything to a database, we must first connect to it. You can connect to virtually any database using the appropriate commands. In this instance, our SQLite database is named ‘PatientData.sqlite’ and it is located in iNTERFACEWARE/Iguana/Demo/Database.

Note: SQLite is a database package that comes with Iguana.

function PatientSearch(Name,Format)

The PatientSearch() function is the meat of this script. We’ve designed it to a) search the database for specific message data (in this case, last names), b) populate a ‘Results’ table with the found data, and c) convert the table into either JSON or XML results that can then be pushed out to the URL. Let’s review this function line by line:

local Result = {}

This command creates a blank table called ‘Results’. We will use this table to store the information that we pull from the external database.

Note: In Lua, curly braces {} indicate a table data type.

local R = DB:query('SELECT * FROM Patient WHERE LastName = '..DB:quote(Name))

This command searched the database for ‘LastName’ values. We use DB:quote to get the correct SQL syntax with the proper quotes. This also helps prevent SQL injection errors.

We have also created a variable named ‘R’ that we will use to place the results.

if Format == 'xml' then
    Patient = xml.parse{data="<Patient Id='' FirstName='' LastName='' Gender=''/>"}.Patient
    print(Patient)   
else
    Patient = {}
end

This conditional statement helps the script choose how to convert the table, once it has been populated:

  • If this is XML, then we will take the basic XML structure that we call ‘Patient’ and parse that with xml.parse to get a blank node tree for the XML with our fields.
  • If this is not XML, then we will just create a blank table called ‘Patient’ that can be converted to JSON
Patient.Id = R[i].Id:nodeValue()
Patient.FirstName = R[i].FirstName:nodeValue()
Patient.LastName  = R[i].LastName:nodeValue()
Patient.Gender    = R[i].Gender:nodeValue()

This statement loops each result to retrieve every relevant field and insert into them into the ‘Patient’ table.

if Format == 'xml' then 
    Result[i] = Patient:S() 
else 
    Result[i] = Patient 
end

This code builds the ‘Result’ table and populates it with the results of our database search.

if Format == 'xml' then
    local Output = "<AllPatients>"..table.concat(Result).."</AllPatients>"
    return Output, 'text/xml'
else
    -- if NOT xml then Serialize 'Result' with json.serialize
    return json.serialize{data=Result}, 'text/'..Format
end
end

This conditional statement performs the final formatting (either XML or JSON) and returns the results.

  • To build XML, we place each field into the converted table and string the results together with table.concat. We also wrap those results with an XML root: <AllPatients>..concatenated results..</AllPatients>
  • To convert to JSON is even easier! Simply apply json.serialize and include your table in its parameters.
Usage=[[
<h1>USING IGUANA AS A WEB SERVICE</h1>
<p>To use this web service, please supply the following parameters:</p>
<ul>
   <li><b>LastName:</b> Please provide the last name of the patient you would like to find.</li>
   <li><b>Format:</b> Please specify if you would like your results in XML or JSON format</li>
</ul>
<p>
The following are pre-formatted requests that you can use to search for a patient with the last name "Smith".
</p>
<p>
Return the results as XML: <a href='?LastName=Smith&Format=xml'>http://localhost:6544/lookup?LastName=Smith&Format=xml</a><br>
Return the results as JSON: <a href='?LastName=Smith&Format=json'>http://localhost:6544/lookup?LastName=Smith&Format=json</a>
</p>
]]

The final section of this script define a set of links that appear when you first open the URL. This allows users to make the web call by simply clicking on a link.

Leave A Comment?