Gentlemen: Brian: thank you for volunteering to coordinate the MacPerl column! Please find appended a first draft of an idea I had. I originally sent this to Vicki, unfortunately the day before she had to resign. I have yet to spend much time on it, so if y'all just don't like it, that's fine. If you do like it, I certainly expect to spend some more time on it; I have no idea if the length is anywhere near correct, for example. If you do like it, someone who has a clue as to the inner workings of the MacPerl CGI glue probably should vet it for fatal errors. Let me know what you think. -David- There are three reasons you might want to run MacPerl cgi scripts on your Mac: 1) You would like to use it to test cgi scripts before uploading them to a production server. 2) You want to take advantage of all the work that has been done developing web clients to add an easy user interface to your MacPerl program on a private network or even a single Mac. 3) You want to run a public web server on your Mac. In my experience, MacPerl works excellently for prototyping, works well on a small, local network, and with care can manage a lightly loaded public server. In this column I will outline my experience, pointing out hints and pitfalls I have discovered along the way. Differences between MacPerl and Unix Perl: ----------------------------------------- In my experience, the two most vexing differences between MacPerl and Perl running under Unix both have to do with differences between the Macintosh operating system and Unix: 1) Interprocess Communication models (AppleEvents on the Mac vs Pipes and Environmental Variables on Unix) are utterly different. In general, interprocess communication is more difficult to use and much less generally available on a Mac. Thus, any Unix perl program which makes use of interprocess communication is going to be more difficult to port to MacPerl. In my opinion, use of pipes is a bad idea for CGI's anyway, so this is not a major problem. The one place the differences between Unix and MacOS IPC might have been a problem is communication between the HTTP server and the CGI. This is not a problem for two reasons: 1) Chuck Shotton, when he wrote MacHTTP (the predecessor to WebSTAR), defined a standard for how HTTP servers should communicate with CGIs on the Mac, and as best I can tell, all Macintosh HTTP servers adhere to that standard. 2) MacPerl has an extension which allows it to communicate via this protocol in a way which is entirely transparent. As a result, no changes should be required to move a CGI from Unix to MacPerl to Unix. 2) Unlike Unix, the Macintosh OS can only run one copy of any given program. Thus, under Unix, you can have 5 copies of the same CGI or 5 different CGIs running at the same time. Under MacOS, you can only have one MacPerl CGI running at a time. In addition, and for reasons I don't fully understand, this also makes it more problematic to implement "server push" using MacPerl. Mechanics of Running MacPerl CGIs: --------------------------------- The MacPerl interpreter comes in two forms; one which can be run with MPW and/or toolserver and a stand-alone application. I will only discuss the latter form. When you save a Perl script from the application, you have a couple of options as to how to save it: 1) Plain text. The script is included as Macintosh text in the data fork of the file. 2) Runtime version. The script is included as a resource in an application which includes a complete copy of the MacPerl interpreter. The resulting file is quite large. 3) CGI. The script is included as a resource in an application which accepts AppleEvents from a Macintosh HTTP server and passes them along with the script to the MacPerl interpreter. The resulting file is small (though a bit larger than plain text.) 4) Droplet. The script is included as a resource in an application which accepts drag and drop events and which passes them along with the script to the MacPerl interpreter. For running a CGI on your Mac, you want to save it as CGI. For transferring a CGI to a Unix server, you want to save it as Plain Text (and then transmit it as text so that the Mac newlines get converted to Unix newlines). The script itself is identical to a Unix CGI. The ever popular CGI.pm module is just as useful on the Mac as it is on Unix. Thus, I won't explain how to write a Perl CGI here, you can read about that in hundreds of places. To run this script as a CGI, you need a Web server (MacHTTP/WebSTAR, Quid Pro Quo, and the web sharing option in the more recent versions of the MacOS all work fine, as probably will any other Mac HTTP server.) Put the MacPerl CGI where your HTTP server expects cgi's, name it as your HTTP server expects it to be named, and it should work. Naming turns out to be fairly critical in many cases. The safest bet in every case of which I am aware is to put ".cgi" (without the quotes) at the end of the filename. There is no such thing as a filename extension on the Mac, and it is unusual on a Mac for the filename to determine function, but HTTP servers are an exception. The other name you might use in some circumstances is one ending in ".acgi". The ".cgi" extension signals to at least some webservers that the file is a cgi to be executed, but that it can accept only one request at a time, so that multiple requests need to be queued. The ".acgi" extension signals to these same HTTP servers that the file is a cgi to be executed, but that it allows threading; that it can accept a new request while a previous request is still running. MacPerl is based on Perl 5.004 and does not allow threading, so one would think (correctly, in most cases) that ".cgi" would be the correct extension for a MacPerl CGI, but as we will discuss later, the ".acgi" extension is unfortunately also the signal that server push should be used, so there are some circumstances where you will want to name your MacPerl CGI with the ".acgi" extension. When a web browser requests your CGI, it will begin running, service the request, and remain running for 5 minutes. This allows the CGI to service multiple requests more quickly as it doesn't have to restart each time. The one disadvantage to this behavior is that if you are developing a script, you have to stop the CGI before you can restart a new version. If you are running everything locally on one Mac, this is not a serious inconvenience; just select the CGI from the application menu in the right end of the Macintosh menu bar and click on the "Quit Now" button. If you are developing on one Mac and running on a physically distant Mac, this can be frustrating, as you have no choice but to wait for the first instance of the CGI to time out before replacing it with a new one. Using resedit, it is possible to reduce this interval to as short as 1 minute (or to increase it), but you will always have to wait at least one minute. The procedure for doing this is detailed in MPPE. In addition to launching the CGI, you will also launch MacPerl. Under default conditions (e.g. if you run an unmodified Unix CGI), MacPerl will continue running until you stop it manually. By adding the following line to your script: #### ....you can instruct MacPerl to quit when the CGI has completed. Complete instructions for accomplishing this are in MPPE. Testing CGI's that will Eventually Run under Unix: ------------------------------------------------- If the CGI uses server push, name it with a ".acgi" extension. Otherwise, name it with a ".cgi" extension. If you use the ".acgi" extension, be sure never to make a second request to the CGI before the first has completed; doing so can crash the server. Other than that, save the script as a CGI while testing it on the Mac, then save it as Plain Text for transfer to Unix. If it works on a Mac, it will work on Unix, and in most cases, vice versa. The only things to watch out for are: * MacPerl is Perl 5.004. 5.005 and later features won't work. * Make sure that any modules or other code you "use" or "require" is available on both the Unix server and the Mac. Remember that modules which have binary extensions may be difficult (or even impossible) to port. * Remember to set your ownership and permissions correctly on the Unix server. Using a CGI to Provide a User Interface for a MacPerl Program: ------------------------------------------------------------- Everyone knows how to surf the Web. Thus, if you are developing a MacPerl program that is going to be used by a number of people in your organization, using the Web to provide a user interface has a number of advantages: 1) You probably already know how to create web pages and forms. In any case, developing for the web is easy. Thus, you can get a user interface up very quickly. 2) If you have an intranet, this gives you a client/server architecture almost for free. 3) Because everyone knows how to surf the web, and everyone has a web browser on their computer, little or no training or software installation will be required. There are a couple of disadvantages: 1) The Web is stateless. Thus, saving state requires more work on your part. But if you have programmed for the web, you already know that. 2) MacPerl CGIs can be a little unstable. This is described in more detail in the next section. Usually, however, this use of MacPerl CGIs involve relatively light loads and thus this is not a problem. Using a MacPerl CGI on a Public, Macintosh Web Server: ----------------------------------------------------- The MacOS is not a server OS; the fact that it works as one at all is what is surprising, not that it doesn't work perfectly. I am currently running a Web server on a Mac, and as of this typing it has been up for 170 hours. (This is about as long as I go without a reboot.) This is a fairly complex database-backed site which in addition to a Web server (Quid Pro Quo), is running a mail server (Apple Internet Mail Server) and a name server (MacDNS), and so is running 9 applications all the time; I think this speaks well for the Macintosh as a server. (As it happens, MacPerl is not a major part of this site for reasons that have nothing to do with MacPerl and everything to do with what the site does.) There are a number of things one can do to improve the stability of the Mac as a server; plenty of RAM, allocating plenty of RAM to all applications, dedicate a Mac as a server rather than try to use one Mac both as a workstation and a server, remove as many extensions as possible, run the shareware utilities "Keep It Up" and "Autoboot" among them) but having done as much of that as you can, there are some MacPerl specific issues as well: 1) Server push is a very useful feature of the Web which allows for simple animations as well as returning data a little at a time when a CGI returns a large amount of data and/or returns it slowly. The latter is important as it keeps the browser or user from timing out. Unfortunately, I have to recommend that you forgo that feature with MacPerl CGIs. To "turn on" server push in a MacPerl CGI, you change the extension of the name from ".cgi" to ".acgi". (I don't know why this is, or if this is a feature of MacPerl or Macintosh-based HTTP servers.) Unfortunately, this also signals to the HTTP server that your CGI is "asynchronous", that it is threaded and can handle multiple hits at one time. This is not true for MacPerl, and when a MacPerl ".acgi" receives a second hit while the first is executing, bad things happen, ranging from dropped hits to crashing the server. For testing a CGI prior to moving it to a Unix server, ".acgi" is very useful as the tester can just be careful to observe its limits. It might even have a place when you are using HTML to provide a front end to a MacPerl program if you can be pretty sure that you will never have overlapping hits and/or where user sophistication and access to the server mean that the occasional crash can be tolerated. I cannot imagine circumstances where this would be acceptable on a public server, however. 2) MacPerl CGIs have fairly high overhead, at least at startup. Further, only one CGI can run at a time. If you use the ".cgi" extension to the CGI name, overlapping hits will be queued and executed in order. This is acceptable when you have fairly few hits. If you are trying to develop and amazon.com or a slashdot, however, I suggest you use other tools. David Steffen, Ph.D. President, Biomedical Computing, Inc. <http://www.biomedcomp.com/> Phone: (713) 610-9770 FAX: (713) 610-9769 E-mail: steffen@biomedcomp.com # ===== Want to unsubscribe from this list? # ===== Send mail with body "unsubscribe" to macperl-request@macperl.org