Develop Web applications for local use

Learn when a browser is better than a GUI application, and when a CGI is best of all


The vast majority of Web sites you visit are presumably open to Internet access, but many companies have found that Intranet development has its place. However, you can take this further -- you can develop perfectly functional Web applications that will never send so much as a single packet over a network interface. Experienced Web developers sometimes find themselves struggling to learn a GUI toolkit when a simple CGI script would serve their needs perfectly well.

A local-only Web application is, if anything, much simpler than one intended for general use. You can easily set browser requirements, and server performance is very unlikely to be an issue. Simple applications, using standard CGI form widgets and the like, can be written in a fraction of the time required for development of self-contained applications. Applications that are built around forms or data manipulation are often excellent candidates for implementation as a trivial Web service.

In many cases, a custom application like this can provide an elegant and simple solution to a very specific problem. I once wrote a picture browser that did nothing but browse a single directory full of files from a camera and let me file the pictures into categories. This took maybe twenty lines of Perl, and the result was much faster than a more general solution, to say nothing of how long it would have taken to write a GUI application to do the same thing.

What has the Web browser done for us, anyway?

You might ask, quite reasonably, Why would anyone bother? What does the Web browser do that another application can't do? The answer is obvious: nothing. But then, what do high-level languages do that you can't do in machine code? Nothing, really. The advantage of using a Web browser as your interface is that all the hard code has been written already. You don't have to run around checking for resize events, window expose events, or menu events. All you do is read a chunk of data expressing a request and process it.

The potential weakness of Web-based development is lack of control over appearance. This is not much of a weakness. If you're trying to get an application developed quickly, the last thing you want is to spend a lot of time messing about with appearance. Whatever platform you're on, the Web browser's native buttons and text widgets will be familiar to the user. That's a feature, really.

The Web browser does one more thing that is very useful: It gives you a number of preference settings you're not required to maintain yourself. Font sizes can be changed by the user on the fly. Similarly, if you can generate your output in a nice, simple HTML form, it can be printed easily and quickly. Many features you might otherwise have to implement (saving output to a file, printing output, and resizing windows are just some examples) are implemented for you.

Architecture for the single user

Although it might seem that a single-user environment completely eliminates a lot of application development considerations, this isn't quite the case. I recently wrote a document-filing system as a Web application. Because I designed it for a maximum of one simultaneous user, I felt I could dispense with a lot of the file-locking code that might otherwise be necessary. I was wrong. The user interface utilized frames, and one of the sanity-checks performed by my display program could fail catastrophically if another program modified the database while it was running. The browser would often end up running both queries at once.

A local server means that network bandwidth is not an issue; even things that might be problematic on ethernet are not a problem on a local host, although huge files will still slow down or crash browsers.

Network security

If you are developing an application to run on a local Web server, give thought to the question of what happens when someone else accesses it over the network. Ideally, ensure that the local application is only accessible on the local network interface. If you can't do that, you will need some kind of security. It might be enough to simply have your application refuse all connections that aren't from, which is a lot more secure than password-based security.

It might be reasonable to simply pick an alternative port number so you can have a dedicated server for your application. On a UNIX®-type box, setting up a personal copy of Apache on port 8880 will take minutes and gives you complete control over server features and settings. It also ensures that your application back end runs with your usual privileges, so you don't have to make crucial files world-writeable, which is a big plus.

Data management

For a traditional Web application, using a database server on the back end simplifies development immensely, because the database engine -- just by being a single server -- provides most of the serialization and locking you need, and more can be obtained easily. For a single-user application that's going to run on a single machine, this is probably overkill and might not be worth the trouble. A local application might have no need of this and might benefit from using a simple and easily moved data file. I would move my document-filing application between my laptop and desktop computers whenever I went anywhere. This was trivial because it simply used a Berkeley DB file.

The Berkeley DB format offers a fairly simple solution that is easily accessible from a number of languages. Because there's no database server involved, it's a poor choice for an application with many simultaneous users; to be safe, you have to lock the database, perform your operations, and then unlock it. On the other hand, because no database server is involved, it's a fairly good choice for a program with very few simultaneous users.

Here's sample Perl code to attach to a Berkeley DB database, complete with locking:

Listing 1: Attaching a database
my %db;
open(DBFILE, '+file.db');
$dbhandle = tie %db, 'DB_File', 'file.db', O_CREAT|O_RDWR, 0666, $DB_HASH;

After this code has run, you can access the database directly as a standard Perl hash:

Listing 2: Using a database
$db{user} = "me";
print "<p>User: $db{user}</p>\n";

You can also use the dbhandle object to perform operations on the database:

Listing 3: Using a database handle

When you're done, you're done -- that is, when your program exits, the lock is dropped automatically. The flock() locking is purely advisory -- it won't prevent other programs from writing to the file if they don't use it. If your program is implemented as a number of related programs, put the locking code in all of them, or better yet, put it in a shared module. This way, the purely advisory locking still gives you what you need: reliable assurance that only one program at a time is modifying the data files.

Some applications will work fine with plain files, such as CSV files or just flat field text files. Some might need a full SQL database. Don't feel compelled to adopt "enterprise-class" solutions for small applications that are intended to get a job done quickly and easily. Save your effort for good error recovery and nice convenience features. That said, if you need a relational database, use one.

Interface widgets

Applications are probably reasonably well addressed using forms with lots of buttons in them. If you have metadata or context that needs to be passed from one page to another, go ahead and use hidden form fields; the security concerns you might face (users can override them) are non-issues in this context. You can use image buttons for many purposes, although they do require you to develop images. If you want to bypass this, create an image button with alt text and an invalid URL for its image:

Listing 4: A text-only button without GUI widgets:
print $q->image_button(-name => "sort",
          -value => "$name",
          -src => "/nonexistant",
          -alt => $label);

This might seem ridiculous, compared to the simpler alternative of just using a hyperlink, but in a large form, the corresponding href=... link might be quite large, and indeed impossible to precalculate if the button is submitting a form. It's an ugly hack, but it works.

One-off applications

If you write a couple of small local host Web applications, you will quickly notice something: They are often quick enough to write, even with debugging, to be substantially more efficient than performing common tasks by hand. The efficiency gain of simplifying a long or tedious procedure might easily pay back the development time of an application that might take only minutes to develop.

Perl's standard CGI library provides a huge variety of useful basic tools to work with. A couple of hours of playing around with it and getting used to its extremely flexible and rich feature set will let you write a broad variety of applications with very little effort. Just as a simple scripting system can make one-off command line scripts practical and cost effective, simple CGI scripts can make a variety of graphical programs practical and cost effective. If you put an afternoon into playing around with these, you'll quickly find that dozens of tasks that you wish someone would have written a program for are easily within your grasp.

Scaling up

A disturbingly common experience is to write a small, simple, one-off application, quite possibly intended only for local use, and then discover that there's a compelling reason to scale it up to a larger audience.

Even when an application is only for local use, write clean code, and have lots of instrumentation and debugging output available. Good code with good support for debugging pays for itself in maintenance costs very quickly. When you add in the possibility of needing to rework the application for a larger (plural!) audience, it pays off even more.

Refactoring can be a fair amount of work, but it's not as bad as you might think. For the most part, it will mean scaling up the actual back-end database or file manipulation to allow for better and smarter locking. If your program does file manipulations, you might consider writing a small server that handles these operations atomically, and thus guarantees serialization. It might well make sense for such a server to handle only one client at a time, as long as individual scripts run quickly.

The major thing you need to watch out for is a program that assumes something about internal state. For instance, in a document-classification program, the obvious thing to do is to display "the next file" to the user, then file it appropriately. With two users, you need some tracking of which file each user is processing, and some way to handle edge cases -- if someone opens the application, then wanders away at some point, you will need to let someone else look at the file in question. Sometimes this can involve a substantial rework of the back end, but it will generally be pretty easy to keep the user-visible front end stable.

Downloadable resources

Related topics


Sign in or register to add and subscribe to comments.

Zone=Web development, Open source
ArticleTitle=Develop Web applications for local use