Adding Interactive Services To Your Web Server
Look around the World Wide Web, and most of what you'll find today are online equivalents of printed propaganda. There may also be some downloadable files or imagesæas well as the seemingly requisite overabundance of hypertext links to every imaginable corner of the Internet. But, for the most part, Web servers are about as interactive as their paper-based counterparts.
While getting to this level of highly-functional-yet-somewhat-interoperable online publishing can seem miraculous to many, it is far from where these systems need to be if they are ever to be something more than an outlet for marketing's creativity. In order for the Web to become the next-generation platform for distributed computing, it must go beyond read-only into the world of interactive. Users should be able to add, edit and delete data in real time, as security and application locking allow.
We'll outline some of the concepts and technologies to help you get there today. We'll also look at some basic examples, and provide pointers to other materials where appropriate and available. By no means can we cover everything. We will attempt to give you enough information so that you can get started in the right direction.
"What kinds of applications can be called from the server, and where can they be found?" These are the two most common questions asked at this point. Before we can answer these questions, we must first look at how the server and applications communicate.
The Common Gateway Interface (CGI)
Most, but not all, Web servers have two basic methods of handling back-end data. They either read a file or communicate with other programs through the Common Gateway Interface (CGI). It's up to the application to figure out what to do with that data, and to return HTML to the server. This is an extremely simplistic overview of the process, and there are many possible exceptions and extensions.
Examples of CGI can be seen on many servers today. Clickable image maps such as those found on Network Computing's home page use CGI. The client sends an HTTP request containing the URL and XY coordinates to the server, which passes the coordinates to a local application. The application executes an event that has been associated with those coordinates and returns HTML to the server for delivery to the client. In the case of image maps, most of the time this HTML data consists of an HTTP redirect command that instructs the client to request another document from the servers.
Another common use of CGI is for searching through files or databases (Yahoo and WebCrawler are good examples). A user constructs a query that is sent to the server, which then spawns an application that conducts the actual search and returns the "hits" in HTML form.
So, to answer the question about the kinds of applications that can be called by the server: They include any application that supports CGI on the front end and can generate HTML responses. In fact, you can call almost any program you want, as long as it supports command-line operation.
However, the unfortunate truth is that no two Web servers are alike. They have all been developed with specific audiences in mind and "enhanced" to suit those markets. This means that just because something works with server brand X does not mean that it will work with server brand Y. For example, there are considerable differences between the Netscape server's CGI interface and the O'Reilly and Associates WebSite server's CGI interface, even though they both use Windows NT's cmd.exe command interpreter. The differences between the various Unix shells, Digital's DCL, DOS' COMMAND.COM, and all other platforms, can also impact what you want to do.
CGI Detailed: GET Vs. POST
One of the most common methods of implementing CGI is through the use of GETs and POSTs. In the "Clickable Image Map" figure, the client submitted a URL with a question mark and XY coordinates appended to the end. This method of CGI call is known as a GET. Not only are GETs the oldest, but they are also the default and easiest to implement. Another form of call, known as POST has become more popular, and is generally considered to be much more powerful. The differences between them are subtle, but significant.
The GET method is named for what the client does. It asks the server to GET the HTML document at HTTP://URL?Param. The server sees that the URL points to an executable, calls it and passes it the parameters.
In contrast, the POST method is used when the client submits a block of data to the server. The client is not necessarily assuming that anything will be returned to it, although the connection is still open. In most cases, the server's Webmaster has configured things so that the client is given a thank you message, or response data is sent to the client.
CGI Examples
Let's walk through an example using O'Reilly and Associates WebSite server, since its use of Windows NT's cmd.exe makes it easy to write simplistic demonstration scripts. WebSite can also run on Windows 95, so it's easy to use on a personal system for learning purposes. Besides, you can evaluate it free for 60 days. It's available at http://website.ora.com.
Once the WebSite Manager is downloaded, use the administrative tool to locate
the directory for DOS executables (C:\WEBSITE\CGI-DOS is
the default). Using notepad or some other text editor, create a file called DIRSEARCH.CMD in
that directory and carefully copy the contents of script contents shown at
the bottom of this article and save the file. Using a Web client, connect to
your server and point to http://<servername>/DOS-CGI/DIRSEARCH.CMD
.
Assuming that your server is configured to allow your client to access DOS-based
CGI scripts, you should get an HTML page stating No Files Specified. Don't
worry. This is what we want! Connect again and this time add ?command.com
to
the end. You should see a standard directory listing of all the files named
command.com. dirsearch.cmd is a simple NT batch file that scans
your server's C: drive for any occurrence of a specified file and returns the
directory list to the user. If a file is not specified, then an error message
is displayed. We'll extend this program later, but first we need to examine
it in detail.
Always Test the Data First
The first line in the box below is a parameter test to make sure that a user has supplied a filename. If "%1" is blank (that is, does not exist), then the batch file jumps to the :errlabel label, which returns an error message to the user. Any seasoned programmer will tell you that it's important to test your program inputs before acting on them, and it is even more crucial here for several reasons.
Most important is an open issue regarding system security. There are known weaknesses with many operating systems that allow shell metacharacters to break your script or a called application, thereby exposing your system. It sounds far-fetched, but it happens all the time. By adding keystroke traps to your script, however, you can go a long way toward preventing this from happening. Refer to the CERT archives for more information on this subject. This weakness is not prevalent on all systems, but it is on many of them.
Another good reason to test the parameters is for program control. As we'll show below, you can use this function to minimize your development. Finally, there's a programming reason to test the input: to make sure that the data is valid. If instead of conducting a directory search, you queried a database, you would want to make sure that all of the necessary information had been provided. Testing the data in a script is more efficient than letting the called application fail. You would still have to test for errors, so you might as well do it up front.
Define Your MIME Type
The use of MIME types to coordinate data exchange is now part of the HTTP specification, as of version 1.0. As you can see, both the :goodlabel and :errlabel sections begin with MIME type declarations echoed to STDOUT.
For our purposes, we are simply declaring that the following data is HTML. The Web client interprets this and knows to read and apply whatever HTML formatting tags it sees in the data. If the MIME type had not been declared, then your browser may or may not interpret the HTML tags.
As you may have guessed, you can also send binaries or other nontext data back to the client. For example, if you wanted to return a GIF image, you would define the MIME content-type as Image/GIF. The client would then receive and display the image appropriately. Likewise, you could send application binaries by using the Application/Octet-stream MIME type, and so on. Note the echo statement that follows the MIME declaration. You must send a blank line after you send the content-type: statement.
The Rest of It
The remaining code is fairly self explanatory. There are, however, some things
worth noting. Notice that the < and >
characters are proceeded by ^. This is to prevent cmd.exe from
interpreting them as redirection commands. Also notice that DIR C:\"%1"/s
is
the actual command that we are calling. The remaining lines of code are used
to prepare the environment and command line, as well as generate HTML on its
behalf.
Image map servers and dynamic directory builders are two of the more common CGI-aware applications that you'll find. Additionally, there are a variety of third-party tools, such as database requesters and indexed searching agents, available on the Internet. If you wish to write your own, you can apply the same concepts we've shown you to a compiled language.
Adding Support for Forms
In its current form, dirsearch.cmd must be given a parameter on the URL's command line. This is far from intuitive, and if you made your users work like this, you'd have very little traffic on your site. Most users prefer to enter information on a form, and so do administrators, since the level of control increases tremendously.
The easiest way to build a form is through the use of the <ISINDEX> HTML tag. This simple tag has the delightful affect of putting an edit box widget on your page. When a user enters text into the edit box and presses the enter key, the text is appended to the URL (with the question mark), and the page is reloaded. At this point, a valid search string exists, and the script will process accordingly.
For our example, change the line in dirsearch.cmd that
reads ^<H1^> No
Files Specified^</H1^>
to Enter a filename to search for:
^<ISINDEX^>
. Now point your Web browser to /BIN/CGI-DOS/DIRSEARCH,
and you will be greeted with an edit box. Type in COMMAND.COM
and
press enter, and the same script will now branch through the :goodlabel
section,
and return a directory listing.
Don't be confused by the name ISINDEX, it's an unfortunate moniker for such a flexible gizmo. This tag does not automatically make your documents searchable; some other tool (such as DIR, in our case) must do the searching if that's what you want. The <ISINDEX> tag simply provides an edit box whose contents are appended to the current URL.
Just as the <ISINDEX> tag is poorly named, so is it poorly treated by most browsers. Many of them prepend the edit box with an inane comment about the document being searchable, which is just plain wrong. In order for us to have an attractive form that doesn't confuse people, we'll have to use real forms.
Creating Real HTML Forms
Form creation with HTML is a fairly simple task, and as we've shown, passing data with CGI is also straightforward. When you combine these two components' simplicity and strength, tremendous results can develop.
In order to illustrate this, we need to modify our sample code. Edit dirsearch.cmd once
again, and replace the <ISINDEX>
tag with the code shown
in the "ISINDEX Replacement" at the bottom of this page.
Save these changes, and reload our now familiar URL. Now, instead of seeing an <ISINDEX> input field, you should see a real HTML form. When you enter a file name into the edit box and click on the "submit" button, the script will process the directory search and return the list of matching files.
Let's examine this syntax in detail. The line that contains the HTML tag does what you might guess: It notifies the client that the following text contains form elements, until a closing tag is encountered.
There are additional keywords that can be used with the tag, which provide
greater amounts of control. One of these is the Action= statement, which tells
the browser where to send the form contents. By default, the destination is
a URL but it could be any CGI application available to the user. For companies
that have several distributed Web servers, but only one or two CGI servers,
this is a great way to split the load. Also of importance is the Method=
keyword,
which allows you to specify that the query data is to be submitted using the
GET or POST methods as described earlier.
Widget Lingo
Another keyword, the input
tag, has many options, but it basically
applies to almost every type of form widget available. This includes edit boxes,
radio buttons, check boxes and command buttons. The only types of widgets not
controlled by <input> are list boxes (either drop-down or scrollable)
and large, multi-line text boxes, both of which have their own specific tags.
In our example, the first occurrence reads <Input Name="FILENAME">
.
This syntax will create an edit box with the resource name of Filename. The
Name= command associates a name with the control data. After successfully running
a query, look at the client's URL command line. Notice that where it used to
have ?command.com, it now has ?filename=command.com. One final thing to remember
about the Name= option is that it does not apply to command buttons (you'll
see why in a moment).
Notice that we did not explicitly declare the edit box as such. That's because the default of <Input> widget is an edit box. If we chose to do so, we would declare it using the Type=Text attribute. Other valid Type= declarations include Password fields (like edit boxes, only keystrokes are echoed as asterisks), CheckBox, Radio, Submit and Reset.
Additionally, we could preload a string into the edit box by using the Value= statement. This can also be used with password fields, as well as checkboxes, radio buttons and command buttons, although its usage varies widely among them.
The default width (in theory, at least) of an edit box is 20 characters, and the height is one. You can define different sizes using the Size= directive. When setting the width, use Size=W. When setting the height, use Size=W,H. Note that setting the width does not restrict input to that amount of characters, but instead defines the width of the box itself.
One problem with the GET method is that text is appended to the URL as entered. If you let the user enter as much as they want, you run the risk of script or called application failure due to overflown buffers. The Maxlength= attribute is useful for limiting the maximum number of characters that an edit box will accept, thereby limiting your system's exposure.
Altogether, our simplistic <Input Name="Filename">
example
could (and probably should) read as <Input Type="Text" Name="Filename"
Width= 20 maxlength=20>
. Note the use of quote marks around the textual
values; this is an HTML requirement that needs to be followed for maximum compatibility.
Command Buttons
Command buttons are not nearly as complex as the edit boxes; there are only
two possible types. Our example uses the Type="Submit" variety, which
builds the parameter list and appends it to the URL specified by the <Form
Action=....>
tag. The other type of command button is Type="Reset",
which clears the form and resets all of the widgets to their original state.
The only optional attribute that can be set for command buttons is Value=.
In this case, the Value= attribute defines the text that appears on the button's
face. It does not change the button's behavior. For our example, we could change <Input
Type="Submit">
to <Input Type="Submit" Value= "Search">
,
and add another button that cleared the editbox by using <Input Type="Reset"
Value="Clear">
.
And Then Some
You should experiment with the different types of widgets and their optional parameters. Together they provide a fairly comprehensive set of tools for getting user input into your CGI scripts and applications. A good starting place is http://www.ncsa.uiuc.edu/ SDG/Software/Mosaic/Docs/fill-out-forms/ overview.html, and by searching Yahoo's (http://www.yahoo.com) database for "HTML and Forms."
Anyone familiar with other types of graphical forms-based tools will tell you that these gizmos, while handy, are hardly sufficient. New extensions have been added to the HTML drafts that address some concerns, but not all. Vendors are stepping up with products that address these concerns, however, so you should be able to find something that suits your need.
On the back end, Lotus Development and Netscape have both promised to ship HTML filters for their respective groupware products, allowing you to leverage in-form value testing, mathematical functions and the like. How these extensions will be handled by generic clients is anybody's guess. But it is a step in the right direction.
As for the clients, Netscape Navigator 2.0 and Oracle's PowerBrowser clients both promise to offer event-driven scripting language extensions that will allow Webmasters to embed extended controls into the forms directly. Although these clients will perform the functions as directed, it means more work for the administrators, since you may have to support multiple proprietary extensions. Again, it's a step that will drive further standards-based development.
GET vs. POST Revisited
We have been using the GET method to pass data down to our script. The POST
method, which offers more capabilities, deserves some attention as well. To
see a quick demonstration, change the <Form...>
line in dirsearch.cmd to
read <Form Method="POST" Action="/BIN/CGI-DOS/DIRSEARCH">
,
and reload the form again. This won't change the behavior of your script, but
you may receive a security notice from your client.
Remember, we've been using O'Reilly's WebSite. It's CGI interface to cmd.exe is relatively consistent between POST and GET. However, there is one significant difference. WebSite manager generates a unique temporary file that contains the data provided during the post operation. You can sniff through this output file on a programmatic basis if needed, allowing your script to branch according to content. This is extremely handy if you have to allow users to submit large strings of text or binary objects.
Beyond Simple CGI
GET and POST both offer value, depending on your objectives. However, in this implementation theyare also both limited in that they rely on NT's cmd.exe, a character-based command interpreter, as well as require that scripts and applications support the use of STDIN and STDOUT. This precludes the use of Windows-based applications as CGI-callable services.
A handful of vendors are working together to develop WIN-CGI to circumvent this problem. Implemented as a CGI-aware library, you can extend any application for which you have the source code, recompiling it to read and write CGI instead of the more traditional I/O interfaces. Such efforts aren't new. Many sources are available for CGI libraries for various servers and operating systems. Contact your Web server vendor for leads.
Now that you understand some of the concepts behind CGI programming, you should be able to develop applications that communicate between the Web and any data system. Remember to follow the specifications, and do a lot of testing, and you'll come out ahead.
Sample File: DIRSEARCH.CMD
IF "%1=="" goto errlabel :goodlabel echo Content-type: text/html echo. echo ^<html^>^<head^> echo ^<title^>All occurances of %1^</title^>^</head^> echo ^<body^> echo ^<h1^>All occurances of %1^</h1^> echo ^<pre^> dir c:\"%1" /s echo ^</pre^> echo ^</body^> echo ^</html^> goto exitlabel :errlabel echo Content-type: text/html echo. echo ^<html^>^<head^> echo ^<title^>No files specified!^</tile^>^</head^> echo ^<body^> echo ^<h1^>No files specified^</h1^> echo ^</body^> echo ^</html^> goto exitlabel :exitlabel
ISINDEX Replacement
echo ^<Form^> echo Enter A File Name to search for: echo ^<Input Name="FILENAME"^> echo ^<Input Type="SUBMIT"^> echo ^</Form^>