Tricks for pulling apart Iguana Apps

Navigating the back end Lua code of an Iguana app

Contents

A lot of times when people start with apps they aren’t necessarily familiar with using Iguana acting as a webservice.  It’s actually a really nice environment for writing web services because of how you work with HTTP transactions as sample data.

You’re able to easily click through and navigate through the code, see all the live annotations and get the auto-completion etc. just you would if you were working with HL7 or other data formats.  It’s awesome.

Let’s say for instance you were interested in writing a utility that could export iguana channels on bulk. The channel manager has some good code to do that which is found in the iguana.channel library. Now admittedly the documentation is a little thin on that library. But if you understand how to import sample HTTP transactions into the translator it’s dead easy to see exactly how it’s called. This is how we do it.

First of all let’s run the Channel Manager and then export a channel. Then go back into Iguana and go and edit the translator instance which is running the channel manager. In the Sample data control click on the middle and you should see something like this:

Now click on the Add From HTTP Request Log button.  This should bring up a list of recent HTTP requests that you can import, like this:

One can see the POST command to export the channel. It might be necessary to search for it if there is a lot of HTTP activity on your Iguana server. Click on the sample data item and it will imported. This HTTP request will be stored in the Data string variable coming into the function main(). If you are in the main lua module and double click on the data variable you should see something like this which shows the raw text of the incoming HTTP transaction:

Now it’s just a matter of navigating the code through the translator – if the translator is new to you it will take a little getting used to but it’s neat. You can navigate through the entire call tree of the Lua code which is executed with this HTTP transaction and see all the inputs and outputs from each function – it’s makes it easy to understand what is going on. Here’s some screenshots to show what you should be looking for.  Start off by clicking on the ‘serveRequest’ link in the main module, ala:

Then you click on the next function (also confusing named serveRequest). What we’re doing here is just clicking through boilerplate code:

Then we can see that the action was handled by the ‘DoJsonAction’.  Click on that:

Then we’re just about at the function which does the action work – the code looks it up in a hash table (feel free to look at stuff along the way – it will give you an idea how it’s all implemented).  Click on Func:

And now we are the actual guts of what implements this particular action.  It’s not a terrifically long piece of code because it’s using some libraries that are part of the channel manager.

So how does this particular piece of code work? Well – the Credentials object is just a Lua table if you click on the table returned from the ‘getCredentials’ function you’ll see something like this:

I.e. a Lua table with the username and password of this Iguana instance – it’s pulling that out of HTTP basic authentication.  You can dig into the code if you are interested.  We get a Lua channel API object by passing in this table into the iguanaServer.connect().

Then we invoke iguana.channel.export with the right parameters to get the file data for a channel. Now the cute thing about that API function is that it doesn’t write the files directly to disk.  It’s actually gives us everything back in the form of a Lua table.  By clicking on the table and expanding it you should see something like this:

Beauty of having it in memory like this is that it decouples it from the process of what we do with this file data.  In this case we pass this Lua table into a recursive routine which compares the exported files from those on disk already and only writes out those which have changed.  It doesn’t take much effort to do many different things with this data once you have it in this form.

For instance, you could use some of the other APIs like iguana.status() to get a list of all the channels and loop through them all at once and export an entire server.  It’s just a few lines of code using the same library like this with a simple implementation:

 local ChannelList = xml.parse{data=iguana.status()}
 for i = 1, ChannelList.IguanaStatus:childCount("Channel") do
    local D = iguana.channel.export{api=Api, name=ChannelList.IguanaStatus:child("Channel", i).Name:nodeValue(), sample_data=false}
    WriteFiles(Config.config.locations[RepoIndex+1].Dir, D)
 end

You could give a report of what files you are exporting and what has changed.

You could use Iguana’s built in zip capabilities write out an entire zip file of the channel in two lines:

local Data = filter.zip.deflate(D)
os.fs.writeFile("myzip.zip", Data)

So you see it’s worthwhile digging just a little and all sorts of neat things drop out.  We’re always happy to give you hints and help on how you can do things like this.