Introduction
In this quick article we'll learn more about RevOnRockets and how it can help you create web applications. The topics covered today are: using the RevHTTP server, using RocketsDebug and using stacks for web applications. This is just the tip of the iceberg, there's more to talk in future articles but now, let us get this going. We as xTalk programmers have enjoyied a productivity level that few developers can relate, may be just forth and lisp coders can share our experience of building software while you use them in an elegant and iterative process. From the confort of our IDE we can grow stacks, functions and objects as we need them, never stopping for compilation or debug as if those phases were a separate thing, while other developers using other tools need to design, implement, compile and test (...rinse, repeat), we have a unique flow that enables us to develop more quickly and usually better (and with GLX2 it gets even better!!!)
Now, till RevOnRockets appeared, all these benefits we're used were not present when developing web applications. To create such applications we needed to use a text editor to build text file scripts, upload them to our server, try to run it, watch it die, look thru lots of system log files and our own text file debuging so that we learn where the bug is. In one Revolution Conference, I labeled this proccess the "code-upload-explode". I don't like it and I bet you don't like it either. I wanted an easy way to build web applications which I could use the points I like most about Runtime Revolution which are: no need to build an app to test it, no need to stop an app to debug it, be able to develop while running and use stacks and transcript. RevOnRockets put the fun back in web app development.
In a glance, RevOnRockets is a collection of three things: a web server, cgi building libraries, examples. The web server runs inside Runtime Revolution IDE and is compatible with Revolution based CGIs, so instead of uploading to a far away server to test an application, you can do it locally from inside the IDE, this alone is useful but when you discover that you can also use the debugger, this becomes a blessing. Creating web application often needs the same stuff over and over again, so the cgi building libraries included help you by providing common useful functions. The examples show how to use the stuff.
Now, let the web games begin.
Unpacking and runing RevOnRockets
First fetch it from http://www.andregarzia.com/RevOnRockets it is a zip file, you can unzip it anywhere you want. In the RevOnRockets folder, you'll see a folder called "www", thats where the action happens. This folder is your root web folder, your cgi apps and web pages will be inside that folder. Besides that folder you'll see the RevHTTP stack which is named "HTTP.Rev", open it.
Using the RevHTTP stack is really easy, check the "setup" tab to see if you're happy with the port selection, the default port is 8082, if you are, just go back to the main tab and click "start". Clicking this will bring your default web browser up with a welcome page. If you're seeing the welcome page then everything is working well.
Creating the Hello Web cgi
No web development tutorial is complete without a simple "Hello World" cgi. So let us build it. Open the "www" folder, inside it you'll notice lots of examples and some other folders. When you check the welcome page URL, you'll see something like http://localhost:8082 which means, the local machine on port 8082. You'll see that the welcome html page is inside the "www" folder and is called "index.html", this page is the default page that is displayed when the client requests a folder but don't specify the page he wants. In the case of the welcome page, the client specifies the "/" root folder, so RevHTTP looks for "www/index.html". You can test by creating a simple text file inside that folder and naming it "test.txt", if you go to "http://localhost:8082/test.txt", you'll see your file content.
Moving along, you see that inside the "www" folder, there is a folder called "cgi-bin", this is a very special folder for it contains the web applications (aka CGI). While the "www" folder is suited for holding static content such as images, html pages, the "cgi-bin" folder is made to hold your scripts. Let us build a text file inside "www/cgi-bin/" called "helloweb.cgi", take notice that even as the file has a cgi extension, it still a simple text file. Make the contents of the file like this:
#!revolution -ui
global gDataA
on startup
start using "RocketsCGI.rev"
cgiOutput "Hello Web from Runtime Revolution", "text/plain"
end startup
Now access the URL http://localhost:8082/cgi-bin/helloweb.cgi you'll see a plain text printed which reads "Hello Web from Runtime Revolution". When the browser requests that file, RevHTTP executes it's content and it's output is sent to the browser.
Let us examine it line by line.
The first line is a unix shee-bang specifier that flags that the script in the text file is to be run using Revolution, the dash "ui" option tells revolution not to load the graphical user interface.
gDataA is a global array created by the RocketsCGI library, although we don't use it in this demo, I've included it out of habit. It holds all kinds of information, including the params passed in the URL and on POST request.
The startup handler is the first one that is called, so it makes sense to put our logic inside it. For text scripts, it is actually the only one that is called, there's no openstack or opencard, just startup.
We put into use the library known as RocketsCGI (and previously known as EasyCGI), this is a core function library for cgis providing basic features such as cgiOutput function that is able to send data back to the browser using the correct format. The first parameter is the content you're sending back, the second is the mime type of the content.
With this, you created your first CGI. If you'd copy both "helloWeb.cgi" and "RocketsCGI.rev" to your apache web server, it would work the same.
Introducing RocketsDebug, web developer best friend
Now, imagine that building a full useful web application will use thousands of lines, if you have a bug in it, how would you debug it? If you're running on RevHTTP it's fairly easy since the IDE will break on errors and show you useful things but sometimes, you want more. RocketsDebug (previously known as EasyDebug) helps you to debug both local and remote scripts. It works like this, if there's an error during the execution of the CGI, it will trap it and generate a useful report highlighting where the error is (or near where it think it is, sometimes this is tricky).
As an example, pick the previous "helloWeb.cgi" you created and make it like this:
#!revolution -ui
global gDataA
on startup
start using "RocketsCGI.rev"
start using "RocketsDebug.rev"
try
get the name of stack "I don't exist"
cgiOutput "Hello Web from Runtime Revolution", "text/plain"
catch n
cgiError n
end try
end startup
You'll see that I put "RocketsDebug.rev" into use and enclose all the code inside a try/catch block, this is needed for "RocketsDebug" to be able to catch the error. The cgiError function is invoked if the try/catch block fails, this function generates a useful report. If you access http://localhost:8082/cgi-bin/helloWeb.cgi now, you'll see the report and you'll see the cascading error reports flagging the troublesome line in red. In our case, we're trying to access the name of a stack that is not there!
If you simple remove the line "get the name of stack "I don't exist" ", you'll see that the above URL start working again. Very simple. When you're happy with your web application and is ready to deploy it to general public, you can remove the cgiError call and thus prevent people seeing your code (I plan to add email reports soon).
Now let us move to a more fun experiment.
Creating the Tropical Fruit Slideshow Web Application
Now, from inside the IDE, well create and try a simple application. This application will be a 10-slides app showing some tropical fruits from Brazil, nothing fancy, just to give you an idea. This example is not showing the best practices of web app development, it's a simple easy to understand app for educational use.
Step #1 - creating the database
let us create a stack based database for holding our fruits photo and info. For this we create a stack called "Gallery.rev", this stack has a background group of two fields ("title" and "caption") for holding the name of the fruit and a brief text about it. Each card holds a single fruit, like a rolodex. In each card we also place an image of the fruit, the name of the image doesn't matter since there's just one per card. You can open "gallery.rev" from "www/cgi-bin/" and see the stack ready.
Step #2 - creating the web application stack
Instead of putting all our logic inside a text file like we did before, let us use a stack this time. Stacks are better for we can use controls and custom properties while with text files, we need an external place to hold such data. Create a new mainstack and name it "galleryDemo", save it as "galleryDemo.rev" inside "www/cgi-bin", actually this stack is already there since I've included this demo in the examples.
To display a web application, we need HTML. For our slideshow, we'll use a template HTML which is a HTML with placeholders where we'll put our fruit data as needed. Instead of creating an external HTML file, I just put a big field inside the "galleryDemo" stack and named this field "template". Inside this field, I've put the HTML, I am going to use. The final gallery looks like this:
From this shot, you'll see that we need to change the photo, the title and the brief text for each fruit and that the arrows need also change since they need to update themselves to point at the previous and next photo depending on the fruit being displayed.
Now, you've probably noticed that we're not only not using an external HTML file but we're also not using external image files, those arrows are from the bundled metacard compatible icon sets. If you open the "galleryDemo.rev" stack, you'll see that I've added both images to the stack. So how, do we display them in the browser? Simple, just like we used cgiOutput to display plain text, we can use it to display JPEGs or PNG or whatever we want. In the case of the images, we use the "Export" command to export them to a variable and use cgiOuput to send them to the browser like:
export image "left arrow" to myVariable as PNG
cgiOutput myVariable, "image/png"
It's as simple as that. For those that don't know how HTTP and HTML really works and teaching this is beyond this simple article, let me do a fast track explanation on what concerns us. First the browser loads the HTML, then for every image references inside the HTML, it makes a new request asking for it. So in our case, the browser will load the HTML, then it will request the fruit pic and then both arrows. It means that to display a single page of our slideshow, the browser makes four requests (html, photo, left arrow, right arrow). We're going to make our cgi answer all these requests, we could have used external image files, RDBMS or other things, we're making a self contained app here to make it easy to understand and to show the power of revolution.
We can't make the browser call "galleryDemo.rev" directly, we need a text file script to load our stack, I've included "galleryDemo.cgi" which reads like:
#!./revolution
on startup
start using "RocketsCGI.rev"
start using "RocketsDebug.rev"
try
start using "galleryDemo.rev"
catch n
cgiError n
end try
end startup
So what it does is simple putting into use our "GalleryDemo" stack. Now, from this code, we know that the first handler to be called in "galleryDemo" will be "libraryStack" since this is the handler that is called when someone uses "start using" command. The whole web application code is this:
on libraryStack
try
go invisible stack "gallery.rev"
put fld "Template" of me into tTemplate
if gDataA["fruit"] is empty then put 1 into gDataA["fruit"]
go card gDataA["fruit"]
put gDataA["fruit"] - 1 into tPrev
put gDataA["fruit"] + 1 into tNext
if tPrev < 1 then put 1 into tPrev
if tNext > the number of cards in stack "gallery.rev" then put the number of cards in stack "gallery.rev" into tNext
switch
case gDataA["img"] is "fruit"
put empty into tImg
export img 1 to tImg as JPEG
cgiOutput tImg, "image/jpg"
break
case gDataA["img"] is "left"
put empty into tImg
export img "left" of stack "galleryDemo" to tImg as PNG
cgiOutput tImg, "image/png"
case gDataA["img"] is "right"
put empty into tImg
export img "right" of stack "galleryDemo" to tImg as PNG
cgiOutput tImg, "image/jpg"
default
cgiOutput the merge of tTemplate, "text/html"
break
end switch
catch n
cgiError n
end try
end libraryStack
Explaining the code. The global gDataA holds lots of nice information for us to use, it's declared from the start. We enclose all the code inside a try/catch block, we didn't needed that since the text script loader already contain that but still, I've did it out of habit.
We begin by loading our database "gallery.rev" stack which holds all the information on the fruits and by loading the HTML template inside a variable.
If we call this cgi like http://localhost:8082/cgi-bin/galleryDemo.cgi?fruit=1 then this part fruit=1 becomes gDataA["fruit"] = 1, capiche? All the URL parameters are converted into a keyed array and inserted into the gDataA array. So if you called it like http://localhost:8082/cgi-bin/galleryDemo.cgi?fruit=1&name=andre+garzia&favcolor=green then you get the following:
gDataA["fruit"] = 1
gDataA["name"] = andre garzia
gDataA["favcolor"] = green
In our code, we check to see if the user passed a specific fruit in the URL, if he didn't we make fruit #1 the default one. As you can see from the next line, we use the fruit parameter as the card number, and go to that card. In our example we have 10 fruits, so fruit will go from 1 to 10. The next lines check for this boundary making sure we don't end up trying to go to card -1 or 11. We also comput the previous and next slides for and put those numbers inside the tPrev and tNext variables.
Then comes the big switch. This switch is used to check which of our four requests we're answering. It uses URL parameters to check if the browser is requesting the arrows, the photo or the html.
The default case is, it is asking for the html. This case is the one that is triggered when you call http://localhost:8082/cgi-bin/galleryDemo.cgi with no param whatsoever, it sends back the HTML. Inside this HTML we used the double brackets placeholders so that we could glue values to the HTML using the merge call. As you can see on the cgiOuput call of the default switch case, we merge the template before sending it to the browser.
If you check on the HTML template inside the field and look for the
<img class="fruitPhoto" src="galleryDemo.cgi?img=fruit&fruit=[[gDataA["fruit"]]">
It is an image with a class, this class is used by the infile CSS style, just forget it. Take notice on the SRC attribute of the tag. It tells the browser, to get the source of this image, request galleryDemo.cgi and pass to it the following parameters img = fruit and fruit = [[gDataA["fruit"]]], this fruit parameter is merged and becomes the content of that array element so if you requested http://localhost:8082/cgi-bin/galleryDemo.cgi?fruit=3 then that image tags becomes:
<img class="fruitPhoto" src="galleryDemo.cgi?img=fruit&fruit=3">
Checking on the switch again, you'll see the first case where we check to see if img = fruit. This means, hey, the browser wants the fruit photo. We pic the first image we find the the card specified by the gDataA["fruit"], convert it to JPEG and send it back to the browser.
If you checked the images that build the arrows you'll see something similar:
<img src="galleryDemo.cgi?img=left" />
This triggers the switch case that looks for gDataA["img"] = left and sends back the image for that arrow. Those arrows are enclosed into a hyperlink tag that is again similar, for the left arrow for example we have:
<a href="galleryDemo.cgi?fruit=[[tPrev]]">
The tPrev value is replaced by the merge call and shows the previous number depending on the fruit being displayed. So we've build it, a simple slideshow application using images and content from Rev.
Deploying the fruit gallery live on the web
My server already have Revolution running on it. It's just a matter of uploading the linux engine and setting the permissions to 755. Now let us upload the files for the gallery. We should also upload RocketsCGI.rev and RocketsDebug.rev
Remember to set the permissions, both cgis and stacks need to be 755.
PS: I Use NoLobes Interarchy FTP tool for my file transfer needs. It's wonderful, and version 9 is even better!
Just like with our cgi-bin folder, my server also has one, I just put the files in there, like I did with RevOnRockets. Double check if you got the file name case sensitivity right. If your code refers to galleryDemo.rev, then your file can't be gallerydemo.rev. Linux is very picky!
Conclusion
This is just the tip of RevOnRockets. We have libraries for much more and very advanced features which I hope to talk in some follow up tutorial. We worked from inside the IDE, tested and debugged our application without the need to the "code-upload-explode" loop. We used a simple template and a switch statement to make a single CGI, actually a single libraryStack handler, deal with four different roles. We learned how to pass data on the URL and pick it from inside Rev.
RevOnRockets has many more libraries, covering RPC, Email, session variables, cross site URL calls... Stay tunned for more news and keep experimenting with the web.
Andre Garzia
If you don't know HTML, check the w3schools , they have tutorials on HTML and CSS.