Client pull
Server push
Communication
between a user's Web browser and your Web server always begins from the
browser side. The user either enters the URL or clicks on a link
containing a URL to a document on your Web server. The Web browser
contacts your Web server and opens an HTTP communications channel between
the two. The Web server takes the request received from the Web browser,
processes it, and returns the results (usually the document requested)
through the open communications channel. Having sent the results of the
request, the Web server shuts down the HTTP communications channel,
severing the connection between itself and the user's Web browser.
This method of
communication requires you to wait for the user to request information on
your Web server before sending that information. However, under some
circumstances you may want to send the data before the user requests it.
For example, if you wanted to display your company's current stock price
on your Web page, you could easily generate the page from a CGI script
that has access to the current stock price. But once the page is sent to
the user's Web browser, you can no longer update the stock price until the
user reloads the Web page. So, even though you generated the HTML page
with a CGI script, the page will contain outdated data within minutes.
Netscape has devised a solution to this problem by developing two methods
of updating information in the user's Web browser without any action by
the user. These methods, known as client pull and server push, are the
topic of this chapter.
Note: Client
pull and server push are implemented by Netscape through changes to
their Navigator browser software, and are supported by all versions of
Netscape Navigator starting with 1.1. However, most other browsers do
not yet support either of these methods
Client pull
Client pull is the
Web browser requesting, or pulling, a Web document from a Web server
without the user entering a URL, clicking on a link, or pressing the
reload button. From this definition, you might imagine that your Web
browser can wildly start loading any document it chooses. But this is not
the case. Client pull only occurs when there is a special directive in a
document you told your Web browser to request from a Web server. This
special directive is a simple HTML 3.0 tag, <META>, that is used to
simulate HTTP response headers. In other words, directives in the <META>
tag are included with the HTTP response headers sent from the Web server.
For example, when the tag
<META HTTP-EQUIV="Refresh" CONTENT=5>
is included in an HTML document, a Web browser that supports the <META>
tag will include the header
Refresh: 5
with the HTTP response headers that were sent from the Web server.
You can use the
<META> tag and Refresh HTTP response header together to cause a user's Web
browser to reload the current page or load a different Web document after
a specified amount of time. So, a document containing the preceding <META>
tag would reload itself after 5 seconds had elapsed. This reload will
continue to occur as long as the Web browser is displaying an HTML page
with the preceding <META> tag.
As you can see,
client pull does not require any CGI scripting to implement. It is defined
through the use of the <META> tag and the Refresh HTTP response header.
However, you can use CGI scripting along with client pull to extend what
you can do with client pull alone. For example, with a static HTML page
containing a <META> tag that reloads the page every five seconds--as shown
in Listing 8.1 the user would just see the same page being reloaded
endlessly, without seeing any new information. If the same page contained
a Server Side Include that called a CGI script that output the current
date and time from the server, the user would see new information every
time the page reloaded. Listing 8.2 shows the HTML code with a Server Side
Include what the page would look like during one of the reloads.
Listing 8.1: HTML Code for a Static HTML Client Pull
<HTML>
<HEAD>
<META HTTP-EQUIV="Refresh" CONTENT=5>
<TITLE>Static HTML Client Pull</TITLE>
</HEAD>
<BODY>
<H1>This Page Reloads Itself</H1>
This page will automatically reload every 5 seconds. Every time it
reloads, it will look exactly the same.
</BODY>
</HTML>
|
Listing 8.2: HTML Code for a More Dynamic Client Pull
<HTML>
<HEAD>
<META HTTP-EQUIV="Refresh" CONTENT=5>
<TITLE>More Dynamic Client Pull</TITLE>
</HEAD>
<BODY>
<H1>This Page Reloads Itself</H1>
This page will automatically reload every 5 seconds. Every time it
reloads, the current date and time are displayed below.
<P>
<!--#exec cgi="/cgi-bin/date.pl" -->
</BODY>
</HTML>
|
The following
sections include some examples of client pull. The first example
demonstrates how to use a splash screen and uses no CGI script. Because
the splash screen requires no CGI scripting, you do it entirely in HTML.
However, this example contains graphic images that you will not have on
your own Webserver. For this reason, you're supplied with the URL so you
can see for yourself how the HTML code works. Even though client pull is
implemented to HTML, which limits you to static HTML pages, you'll see
that there are still some applications for client pull alone. The second
example creates a guided tour of the Educational Software Web site and
demonstrates how a CGI script can further enhance the client pull feature.
A
Splash Screen
Creating a splash
screen for the first page of your Web site is a creative way to use client
pull without any CGI scripting. A splash screen is an identifying image
that appears when you start a program. Most commercial programs feature
splash screens. For example, Netscape Navigator 2.0 for Windows displays
the image every time you start the program. Using Client pull, you
can create a splash screen for your Web site.
For this example,
you will create the HTML code for a splash screen for the Actors Album Web
site. Because you implement this example by adding a single line of HTML
code to a normal HTML page, you'll see how to create a splash screen for
your own Web site. Start by seeing how the Actors Album splash screen
works. You can do this by visiting the URL http://www. castingguild.com/actors-album/splash.html
using the Netscape Navigator Web browser (a version newer than 1.1). (If
you don't have Netscape, you can download it and try it for free from
Netscape's Web site, http://www. netscape.com.) Looking at the Actors
Album splash screen will give you a better idea of how the splash screen
works. Five seconds later, the Netscape browser automatically sends a
request for the home page. Even though the browser sends the request after
five seconds, how soon the page is displayed depends on the speed of your
Internet connection. Listing 8.3 includes the HTML code for the Actors
Album splash screen.
Listing 8.3: The HTML for the Actors Album Splash Screen
<HTML>
<HEAD>
<META HTTP-EQUIV="Refresh" CONTENT="5;
URL=http://www.castingguild.com/actors-album/">
<TITLE>Actors Album</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER>
<IMG HEIGHT=233 WIDTH=3Ø5 VSPACE=1Ø HSPACE=1Ø
SRC="graphics/splash.gif">
</CENTER>
</BODY>
</HTML>
|
Apart from the <META> tag, this HTML code is similar to the code at
numerous other Web sites. As you learned earlier in this chapter, the
<META> tag drives the client pull action. This version of the <META> tag
is slightly different from the ones you saw earlier. In the attribute
CONTENT is the URL for another document. By specifying the URL in this
manner, you can instruct the Web browser to load a different document
instead of reloading the same one. The line
<META HTTP-EQUIV="Refresh" CONTENT="5;
URL=http://www.castingguild.com/actors-album/">
tells a client pull enabled Web browser to load the URL http://www.castingguild.
com/actors-album/ after five seconds. Remember that when the URL does not
specify a document name (as here), the Web server returns the index.html
file if one exists. The Actors Album's index.html file contains no <META>
tag, so no further client pulls are initiated. In other words, client pull
briefly displays the first page, splash.html, which is followed
immediately by the Web site's home page.
You can easily
implement a splash screen for your own Web site. Simply create an HTML
file that will be the splash screen, and add the <META> tag to the HTML
code of the splash screen file. The code for your <META> tag would look
like
<META HTTP-EQUIV="Refresh" CONTENT="5; URL=Your home page URL">
with your home page's URL specified. Remember that your splash screen will
only work with Web browsers that support client pull. So, if your splash
screen doesn't contain any links to your real home page, as is the case in
the Actors Album splash screen, don't make it the default page for your
Web site. Doing so would strand users on your splash screen page if their
Web browser did not support client pull. They would have no alternate way
to get to your home page.
A
Guided Tour
Now let's take the
client pull feature and extend it by using a CGI script. For this example
you will create a guided tour of the Educational Software Web site. This
Web site has only three pages--the home page, the Software Downloads page,
and the Technical Support page. The guided tour feature will take the user
through each page of the Educational Software Web site, explaining what
information is on each Web page and what the user can do on the page.
Although you can implement a guided tour without client pull, you will use
client pull so the user does not have to click on links to go to the next
page in the tour. In the next sections you will create the Web pages for
the Educational Software Web site and write a CGI script that takes the
user through each Web page.
The
Educational Software Web Pages
To set up the
guided tour for the Educational Software Web site, you first need to
create the home page, Software Downloads page, and Technical Support page
of the Web site. The home page will contain some information about
Educational Software and some announcements about software that is coming
soon or is newly available. Listing 8.4 contains the HTML code for the
Educational Software home page shows the page in the Netscape browser.
Notice there is already a link for the guided tour that calls the CGI
script guided.pl. This is the guided tour CGI script you will be
developing later in this section.
Listing 8.4: HTML Code for the Educational Software Home Page
<HTML>
<HEAD>
<TITLE>Educational Software</TITLE>
</HEAD>
<BODY>
<H1>Educational Software</H1>
Educational Software provides freeware software with an educational
purpose. Currently, Educational Software only has two software titles,
Algebra Primer and Vocabulary Builder, which are both available from
the <A HREF="downloads.html">software downloads page</A>. We are now
working on a third title, Elementary Physics, which should be
available in August.
<P>
If you have Netscape Navigator 1.1 or greater, you can select the <A
HREF="/cgi-bin/guided.pl">Guided Tour</A>, which will acquaint you
with our Web site.
<P>
[ <A HREF="downloads.html">Software Downloads</A> | <A HREF="tech-
support.html">Technical Support</A> | <A HREF="/cgi-
bin/guided.pl">Guided Tour</A> ]
</BODY>
</HTML>
|
Listing 8.5: HTML Code for the Software Downloads Page
<HTML>
<HEAD>
<TITLE>Educational Software - Software Downloads</TITLE>
</HEAD>
<BODY>
<H1>Educational Software - Software Downloads</H1>
<TABLE>
<TR>
<TH ALIGN=left>Macintosh</TH>
<TH WIDTH=5Ø></TH>
<TH ALIGN=left>Windows</TH>
</TR>
<TR>
<TD ALIGN=left><A HREF="algebra.hqx">Algebra Primer</A></TD>
<TD WIDTH=5Ø></TD>
<TD ALIGN=left><A HREF="algebra.zip">Algebra Primer</A></TD>
</TR>
<TR>
<TD ALIGN=left><A HREF="vocab.hqx">Vocabulary Builder</A></TD>
<TD WIDTH=5Ø></TD>
<TD ALIGN=left><A HREF="vocab.zip">Vocabulary Builder</A></TD>
</TR>
</TABLE>
<P>
[ <A HREF="home.html">Home</A> | <A HREF="tech-support.html">Technical
Support</A> ]
</BODY>
</HTML>
|
Educational
Software's Software Downloads page will contain links to all the software
programs that are available for downloading. The software is listed as
freeware--that is, it doesn't cost anything. For this example, the
Software Downloads page contains two programs, Algebra Primer and
Vocabulary Builder. There are Macintosh and Windows versions of the
programs, which the user can download simply by clicking on the
appropriate link. Listing 8.5 contains the HTML code for the Software
Downloads page shows how the page will appear in the Netscape browser.
The Technical
Support page lets users of Educational Software programs send messages to
Educational Software when they have technical problems with the software.
The Technical Support page contains the same elements as the feedback form
in Chapter 4. Listing 8.6 contains the HTML code for the Technical Support
Web page.
Listing 8.6: HTML Code for the Technical Support Page
<HTML>
<HEAD>
<TITLE>Educational Software - Technical Support Form</TITLE>
</HEAD>
<BODY>
<H1>Educational Software - Technical Support Form</H1>
<FORM METHOD=POST ACTION="/cgi-bin/feedback.pl">
<B>Name</B><BR><INPUT NAME="name" SIZE=42>
<P><B>E-mail Address</B><BR><INPUT NAME="email" SIZE=42>
<P><B>Comments</B><BR><TEXTAREA NAME="comments" ROWS=1Ø COLS=38></TEXTAREA>
<P><INPUT TYPE="submit" VALUE="Send"></FORM>
<P>
[ <A HREF="home.html">Home</A> | <A HREF="downloads.html">Software
Downloads</A> ]
</BODY>
</HTML>
|
The
Guided Tour Script
Now that you have
the Web pages for the Educational Software Web site, you can write the
guided tour CGI script that takes users through each Web page of the site.
The guided tour begins when the user selects the guided tour link at the
bottom of the home page, which calls the guided.pl script. The guided.pl
script opens the HTML file for each Web page, adding some new lines at the
beginning (including a line with the <META> tag to do the client pull) and
then returns the modified Web page to the user's browser. After 30
seconds, the user's Web browser sends a new request to the guided.pl
script, which then sends back a modified version of the next Web page.
This process continues until the guided.pl script has sent modified
versions of all the Web pages from the Web site. The guided tour ends by
returning the user to the Educational Software home page.
When the user
selects the guided tour link on the home page, the guided tour script
starts. The script reads in the HTML code for the home page from the
home.html file and modifies it to contain a brief explanation of the Web
page. Also, the script adds the <META> tag in the header portion of the
modified home page. Because you are using client pull for the guided tour,
you need to add this line so the next page loads automatically. Because
the guided tour script needs to modify the Web page before displaying it
to the user, the <META> tag must request the guided.pl script file. The
basic form of this <META> tag is
<META HTTP-EQUIV="Refresh" CONTENT="3Ø; URL=http://www.robertm.com/cgi-
bin/guided.pl?page=pagename.html">
Notice that the guided tour script receives the parameter page=pagename.html
when it is called. This lets the guided tour script know which Web page to
return to the user's Web browser.
The guided tour
script adds the preceding <META> tag to the modified versions of the Web
pages. For the script to work properly, it needs to know which Web page is
to be displayed next, so that it can insert the page name in the <META>
tag. For example, if the current page to be displayed were the Software
Downloads page, the guided tour script would need to insert the following
<META> tag at the beginning of the downloads.html file:
<META HTTP-EQUIV="Refresh" CONTENT="3Ø; URL=http://www.robertm.com/cgi-
bin/guided.pl?page=tech-support.html">
Notice that pagename.html has been changed to tech-support.html. This is
because the Technical Support page is the page displayed after the
Software Downloads page. To know which Web page is next, your guided tour
script needs to keep track of the order in which the Web pages are to be
displayed. You can do this by storing the name of all the Web pages from
the site in an array, like this:
@pages = ("home.html", "downloads.html", "tech-support.html");
The script will display a modified version of each page in the array, in
the order in which they appear in the array. So, for the @pages array, the
guided tour script will first display a modified version of the home page,
followed by modified versions of the Software Downloads page and the
Technical Support page.
Now that you have
the order of the Web pages stored in the @pages array, you can write the
Perl code to have your guided tour script formulate the <META> tag for the
page being modified:
shift(@pages) until $pages[0] eq $data{'page'};
if (@pages > 1) {
$url_prefix .= $pages[1];
} else {
$url_prefix = $homepage;
}
$add_tag = "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3Ø; URL=$url_prefix\">\n";
The first line contains two parts, the shift expression, shift(@pages),
and the until loop. The shift expression removes the first item from the
@pages array. The until loop causes the shift statement to repeatedly
execute until the first element in the @pages array is equal to the value
in the $data{'page'} element. As before, the %data array is the
associative array that stores the data your CGI script receives when
called. For this example, the only data being passed to the CGI script is
the name of the Web page to be displayed. Because you move the name of the
current page to the first element of the @pages array, your script can
always access the next element by referencing the second element in the
@pages array. For example, if $data{'page'} were downloads.html, the first
element of the @pages array, home.html, would be removed. The array would
then contain only two elements, downloads.html and tech-support.html. The
first element, $pages[0], would be the current page to display,
downloads.html. The second element, $pages[1], would be the next page to
display, tech-support. html, and would be the value to insert into the
<META> tag of the downloads. html page.
The name of the
next Web page to be displayed is appended to the URL prefix in the
preceding if...else statement. Notice that the if statement compares the
array @pages to the number 1. When the @pages array is used in this
context, it is referencing the length of the array, not any individual
array element. So, the if statement checks whether the array contains more
than one element. If it does--as in the previous example with the
downloads.html page--the next page, or $pages[1], is appended to the $url_prefix
variable, which is set earlier in the code with the line
$url_prefix = "http://www.thepalace.com/cgi-bin/guided.pl?page=";
Listing 8.8, which appears later, shows exactly where the previous line is
placed. If the @pages array only has one element, which would be the case
when $data{'page'} is set to tech-support.html, the guided tour script is
generating the last page to be displayed in the tour. When the guided tour
is finished, the user is returned to the Educational Software home page.
When the @pages array only contains the one element, the <META> tag needs
to look like
<META HTTP-EQUIV="Refresh" CONTENT="3Ø; URL=http://www.robertm.com/home.html">
So, the value of the $url_prefix variable is changed to the value of the
$home-page variable, which is also set elsewhere in the guided tour script
with the line
$homepage = "http://www.robertm.com/home.html";
After the if...else statement block, the $url_prefix variable will contain
the correct path to be added in the <META> tag for the current page. The
line
$add_tag = "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3Ø; URL=$url_prefix\">\n";
creates the string for the <META> tag and stores it in the $add_tag
variable for later inclusion in the HTML code that the guided tour script
will send back to the user's Web browser.
With the <META> tag
properly formatted for the current Web page to be displayed in the tour,
the script is ready to modify the contents of the existing Web page. First
you will create a variable $guide, which stores the HTML code for the text
to be included at the top of the page. This text is a simple explanation
of the Web page the user is currently viewing in the tour. For example,
with the home page, the text could be
This is the Educational Software home page. It includes announcements about new
and upcoming software releases.
An easy way to include the correct explanatory text for the page to be
displayed is to store the explanations in an associative array keyed by
the names of the Web pages. The following lines do this:
%guide_text =
( "home.html", "This is the Educational Software home page. " .
"It includes announcements about new and upcoming " .
"software releases.",
"downloads.html", "From this page, you can download the freeware " .
"software. There are versions available for both " .
"Macintosh and Windows machines. To download, just " .
"click on the software title under your machine's type.",
"tech-support.html", "Use this feedback form to send us messages when " .
"you have technical problems with our software.", );
Then, to format the explanatory text with HTML tags for inclusion in the
modified version of the Web page, you would write
$guide = "<CENTER><HR>$guide_text{$data{\"page\"}}<HR></CENTER>";
Because the $data{'page'} element holds the name of the current page,
using this for the key of the %guide_text array accesses the correct
explanation for the current page.
Next you need to
open the HTML file of the current page to be modified and displayed in the
tour. You do this with the following three lines, which open the HTML
file, read all of the contents into the @template array (one line per
element in the array), and close the HTML file.
open(TEMPLATE, "$path/$data{\"page\"}") || die "Content-type: text/html\n\nCannot
open HTML files!";
@template = <TEMPLATE>;
close(TEMPLATE);
The first line opens the HTML file for input. The path and file name of
the HTML file are stored in the $path and $data{'page'} variables, which
are set at the beginning of the guided tour script. The die statement
terminates the program and outputs the contents of the string.
The || operator
between the open and die statements is the logical or operator. If you
place this operator between the two statements, the Perl interpreter first
tries to execute the open statement. If the open is successful, the Perl
interpreter moves on to the next line of code. However, if the file cannot
be opened, the Perl interpreter executes the die statement. This is a
common way to verify whether a file has opened successfully and to
terminate the Perl program if it has not.
The second line in
the preceding Perl code reads in the contents of the HTML file from the
input stream <TEMPLATE> and places each line in an element of the array
@template. After the contents of the HTML file have been read into the
@template array, you can close the input stream <TEMPLATE> with the close
command, as in the third line of code.
Finally, you need
to modify the lines of the @template array that will be different for the
guided tour. First you will modify the line containing the <TITLE> tags.
In Listings 8.4, 8.5, and 8.6, the <TITLE> tags are all on the third line
of the HTML file. Because the indexing of Perl arrays begins with 0, you
can change the third element by using the following line:
$template[2] = "<TITLE>Guided Tour - $page_names{$data{\"page\"}}</TITLE>\n";
This line changes the title to Guided Tour - pagename, where pagename is
the name of the page currently being displayed. Because you want to
display the name of the page and not the name of the HTML file, you can
store the names of the pages in the %page_names associative array, which
is keyed by the names of the HTML files. This is done in the following
lines:
%page_names =
( "home.html", "Home Page",
"downloads.html", "Software Downloads Page",
"tech-support.html", "Technical Support Page", );
When the $data{'page'} variable is set to downloads.html, the title line
is changed to
<TITLE>Guided Tour - Software Downloads Page</TITLE>
After modifying the title line, you need to add the lines containing the
<META> tag and the explanation text. You do this with the following two
lines of code:
splice(@template, 5, Ø, $guide);
splice(@template, 2, Ø, $add_tag);
Both lines use the splice operator, which inserts the contents of the
variables $guide and $add_tag into the @template array. In the first line,
the contents of the $guide variable are inserted into the @template array
after the fifth element in the array. This places the explanatory text
right after the <BODY> tag for all the Web pages, as shown in Listings
8.4, 8.5, and 8.6. The second line inserts the contents of the $add_tag
variable into the @template array after the second element in the array.
For all the Web pages, this would place the <META> tag immediately after
the <HEAD> tag, as shown in Listings 8.4, 8.5, and 8.6. The 0 used in both
lines of code indicates to Perl to insert the contents of the variables
without removing any of the current elements of the array.
Finally, with the
@template array containing the modified version of the HTML page to
display to the user, you need to output the parsed header and the contents
of the @template array. You do this with the following two lines of Perl:
print "Content-type: text/html\n\n";
print @template;
Listing 8.7 contains the Perl code that you just finished developing. For
readability, it has been placed into a subroutine called Display. The only
additions are the sub Display line, which declares the name of the
subroutine, and the local variable declarations in the first two lines to
the subroutine. The local statements
local (%data) = @_;
local (@template, $guide, $add_tag);
declare the arrays and variables as local to the Display subroutine. As
you may remember, a local variable is a variable that exists only within a
portion of your Perl code, usually within a subroutine. If a variable with
the same name existed outside the subroutine, Perl would consider it a
different variable than the one that is declared local within the
subroutine. Declaring your subroutine's variables as local helps to keep
your subroutines from overwriting values of global variables. A global
variable is one that is accessible throughout the entire Perl program,
including any subroutines in the same Perl file. In Listing 8.7, the
variables $url_prefix and $path and the arrays @pages, %guide_text, and %page_names
are global variables.
Listing 8.7: The Display Subroutine
sub Display {
local (%data) = @_;
local (@template, $guide, $add_tag);
$data{'page'} = "home.html" unless $data{'page'};
shift(@pages) until $pages[Ø] eq $data{'page'};
if (@pages > 1) {
$url_prefix .= $pages[1];
} else {
$url_prefix = $homepage;
}
$add_tag = "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3Ø;
URL=$url_prefix\">\n";
$guide = "<CENTER><HR>$guide_text{$data{\"page\"}}<HR></CENTER>";
open(TEMPLATE, "$path/$data{\"page\"}") || die "Content-type:
text/html\n\nCannot open HTML files!";
@template = <TEMPLATE>;
close(TEMPLATE);
$template[2] = "<TITLE>Guided Tour -
$page_names{$data{\"page\"}}</TITLE>\n";
splice(@template, 5, Ø, $guide);
splice(@template, 2, Ø, $add_tag);
print "Content-type: text/html\n\n";
print @template;
}
|
To finish the guided tour script, you just need to place the code for the
Display subroutine, listed in Listing 8.7, into the guided.pl file along
with the declarations of global variables and the code for the No_SSI and
User_Data subroutines you have been using throughout this book. Listing
8.8 contains the entire code for the guided tour script. Be sure to change
the $path, $url_prefix, and $homepage variables to contain the correct
paths and URLs for your machine. Also, Windows users should remove the
first line of the script, which is specific to UNIX systems.
Listing 8.8: The guided.pl File
#!/usr/local/bin/perl
# All users need to change the paths and URLs to be correct for
# their machines. Windows users need to have the $path variable
# in the form $path = "c:\\robertm\\guided"
$path = "/users/robertm/guided";
$url_prefix = "http://www.robertm.com/cgi-bin/guided.pl?page=";
$homepage = "http://www.robertm.com/home.html";
@pages = ("home.html", "downloads.html", "tech-support.html");
%page_names =
( "home.html", "Home Page",
"downloads.html", "Software Downloads Page",
"tech-support.html", "Technical Support Page", );
%guide_text =
( "home.html", "This is the Educational Software home page. " .
"It includes announcements about new and upcoming " .
"software releases.",
"downloads.html", "From this page, you can download the freeware " .
"software. There are versions available for both " .
"Macintosh and Windows machines. To download, just " .
"click on the software title under your machine's type.",
"tech-support.html", "Use this feedback form to send us messages when " .
"you have technical problems with our software.", );
if ($ENV{'REQUEST_METHOD'} eq "GET") {
%data_received = &User_Data;
&No_SSI(*data_received);
&Display(%data_received);
} else {
print "Content-type: text/html\n\nYou are not using this script correctly!";
}
sub Display {
local (%data) = @_;
local (@template, $guide);
$data{'page'} = "home.html" unless $data{'page'};
shift(@pages) until $pages[Ø] eq $data{'page'};
if (@pages > 1) {
$url_prefix .= $pages[1];
} else {
$url_prefix = $homepage;
}
$add_tag = "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"3Ø; URL=$url_prefix\">\n";
$guide = "<CENTER><HR>$guide_text{$data{\"page\"}}<HR></CENTER>";
# Windows users need to change the string "$path/$data{\"page\"}" to
# "$path\\$data{\"page\"}"
open(TEMPLATE, "$path/$data{\"page\"}") || die "Content-type:
text/html\n\nCannot open HTML files!";
@template = <TEMPLATE>;
close(TEMPLATE);
$template[2] = "<TITLE>Guided Tour - $page_names{$data{\"page\"}}</TITLE>\n";
splice(@template, 5, Ø, $guide);
splice(@template, 2, Ø, $add_tag);
print "Content-type: text/html\n\n";
print @template;
}
sub No_SSI {
local (*data) = @_;
foreach $key (sort keys(%data)) {
$data{$key} =~ s/<!--(.|\n)*-->//g;
}
}
sub User_Data {
local (%user_data, $user_string, $name_value_pair,
@name_value_pairs, $name, $value);
# If the data was sent via POST, then it is available
# from standard input. Otherwise, the data is in the
# QUERY_STRING environment variable.
if ($ENV{'REQUEST_METHOD'} eq "POST") {
read(STDIN,$user_string,$ENV{'CONTENT_LENGTH'});
} else {
$user_string = $ENV{'QUERY_STRING'};
}
# This line changes the + signs to spaces.
$user_string =~ s/\+/ /g;
# This line places each name/value pair as a separate
# element in the name_value_pairs array.
@name_value_pairs = split(/&/, $user_string);
# This code loops over each element in the name_value_pairs
# array, splits it on the = sign, and places the value
# into the user_data associative array with the name as the
# key.
foreach $name_value_pair (@name_value_pairs) {
($name, $value) = split(/=/, $name_value_pair);
# These two lines decode the values from any URL
# hexadecimal encoding. The first section searches for a
# hexadecimal number and the second part converts the
# hex number to decimal and returns the character
# equivalent.
$name =~
s/%([a-fA-FØ-9][a-fA-FØ-9])/pack("C",hex($1))/ge;
$value =~
s/%([a-fA-FØ-9][a-fA-FØ-9])/pack("C",hex($1))/ge;
# If the name/value pair has already been given a value,
# as in the case of multiple items being selected, then
# separate the items with a " : ".
if (defined($user_data{$name})) {
$user_data{$name} .= " : " . $value;
} else {
$user_data{$name} = $value;
}
}
return %user_data;
}
|
Server push
When you use client
pull, every refresh action taken by the Web browser opens a new HTTP
communication channel. Recall that client pull starts when the Web browser
requests a document containing the <META> tag, which instructs the Web
browser to refresh the document after a specified amount of time. The Web
server always shuts down the HTTP communication channel after the document
has been sent. When the Web browser performs the refresh, it sends a new
HTTP request to the Web server for the same document (or for the new
document specified by the inclusion of a redirect URL, as demonstrated in
the splash screen example earlier in this chapter). Once again, the Web
browser opens communication with the Web server, which returns the
document and closes the communication channel.
Unlike client pull,
server push keeps the HTTP communication channel open between the Web
browser and the Web server. Then, when instructed to, the Web server sends
data to the Web browser through this open communications channel. By
keeping the channel open, the Web server has complete control of when data
is sent to the Web browser. The Web server does not have to wait for the
Web browser to initiate the communication.
Server push is
initiated through a CGI script that holds the communication channel
between the Web browser and the Web server open until the script finishes
executing. You do this by using a variation on the multipart/mixed MIME
type. Recall from Chapter 2 that the parsed header Content-type takes MIME
types for its values. In previous examples, you have used the text/html
and image/gif MIME types. For most HTTP responses, there is only one block
of data sent to the Web browser, which only needs one MIME type for the
data being returned to the Web browser. However, the multipart/mixed MIME
type allows for multiple blocks of data to be sent in the same HTTP
response.
The
multipart/mixed MIME type uses a boundary string to separate the blocks of
data being returned to the Web browser. Each data block has its own MIME
type specified at the beginning of the block. You can use any string for
the boundary separator. However, it's important to use a string that does
not occur in the data being returned. A typical multipart/mixed parsed
header looks like
Content-type: multipart/mixed;boundary=ThisRandomString
where ThisRandomString is the string boundary. As with other parsed
headers, the multipart/mixed must be followed immediately by a blank line.
Then at the beginning of each data block, you place the boundary string
preceded by two dashes, followed on the next line by the MIME type for
that block of data. You must have a blank line between the MIME type and
the data being returned. You must also have a blank line immediately after
the data object. So, the header and data for each block would look like
--ThisRandomString
Content-type: text/html
Data for the first object.
After you have
included all the blocks of data you want returned to the user's Web
browser, simply output the end of boundary string, which is the boundary
string preceded and followed by two dashes, as in
--ThisRandomString--
Here is an example of an HTTP response using the multipart/mixed MIME
type:
Content-type: multipart/mixed;boundary=ThisRandomString
--ThisRandomString
Content-type: text/html
Data for the first object.
--ThisRandomString
Content-type: text/html
Data for the second and last object.
--ThisRandomString--
This example contains two
HTML objects that are returned to the user in the HTTP response.
Server push uses a variant of
the multipart/mixed MIME type, the multipart/x-mixed-replace MIME type.
This is an experimental MIME type created by Netscape for server push. The
difference between this MIME type and the standard multipart/mixed MIME
type is that multipart/x-mixed-replace replaces previous data blocks with
the subsequent data blocks. The format for the multipart/x-mixed-replace
MIME type is identical to the above multipart/mixed example. Simply change
the first line to
Content-type: multipart/x-mixed-replace;boundary=ThisRandomString
The major drawback with server push is that the HTTP communications
channel remains open until the Web server is finished sending all the
data. This means that your Web server must dedicate a TCP/IP port to the
user's Web browser for the duration of the server push. When you use
server push, you can keep this channel open indefinitely, sending data
down whenever you want. Because all systems have a limited number of
TCP/IP ports, this might overload your Web server. For this reason, you
should use server push with discretion, especially if your Web server
machine has limited TCP/IP ports.
The Pushed Guided Tour
Using server push, you can
redo the guided tour script to push down the modified pages instead of
having the Web browser pull down the pages. This makes your guided tour
script much simpler, because it does not have to receive any input about
the current page to display. The script is only executed once for the
entire guided tour instead of once for each Web page as with the client
pull guided tour. The script just has to loop over the @pages array and
send down the proper header and modified Web page for each element in the
@pages array. Listing 8.9 contains the Perl code for the server push
guided tour. To run this guided tour, place the code in a file called
push-guided.pl (or p-guide.pl if you are restricted to an eight-character
file name) and use the same three HTML pages from the client pull guided
tour, as shown in Listings 8.4, 8.5, and 8.6. All users need to make the
specified change to the path variable. Also, Windows users need to remove
the first line and change the file names in both open statements, as noted
in the comments.
Listing 8.9: The push-guided.pl File
#!/usr/local/bin/perl
# All users need to change the path to a valid path for
# their machine. Windows users need a path in the form
# $path="c:\\robertm\\guided";
$path = "/users/robertm/guided";
@pages = ("home.html", "downloads.html", "tech-support.html");
%page_names =
( "home.html", "Home Page",
"downloads.html", "Software Downloads Page",
"tech-support.html", "Technical Support Page", );
%guide_text =
( "home.html", "This is the Educational Software home page. " .
"It includes announcements about new and upcoming " .
"software releases.",
"downloads.html", "From this page, you can download the freeware " .
"software. There are versions available for both " .
"Macintosh and windows machines. To download, just " .
"click on the software title under your machine's type.",
"tech-support.html", "Use this feedback form to send us messages when " .
"you have technical problems with our software.", );
$|=1;
print "Content-type: multipart/x-mixed-replace;boundary=ThisRandomString\n\n";
foreach (@pages) {
print "--ThisRandomString\n";
print "Content-type: text/html\n\n";
$guide = "<CENTER><HR>$guide_text{$_}<HR></CENTER>";
# Windows users need to change the string "$path/$_" to
# "$path\\$_"
open(TEMPLATE, "$path/$_") || die "Content-type: text/html\n\nCannot open HTML
files!";
@template = <TEMPLATE>;
close(TEMPLATE);
$template[2] = "<TITLE>Guided Tour - $page_names{$_}</TITLE>\n";
splice(@template, 5, Ø, $guide);
print @template;
print "\n\n";
sleep 3Ø;
}
print "--ThisRandomString\n";
print "Content-type: text/html\n\n";
# Windows users need to change the string "$path/home.html" to
# "$path\\home.html"
open(TEMPLATE, "$path/home.html") || die "Content-type: text/html\n\nCannot open
HTML files!";
@template = <TEMPLATE>;
close(TEMPLATE);
print @template;
print "\n\n";
print "--ThisRandomString--\n\n";
|
The first thing you should
notice in Listing 8.9 is the line
$|=1;
This is a special Perl variable that, when set to a nonzero value, forces
a flush of the output stream (standard output in this example) after every
print statement. In other words, it keeps the output stream from being
buffered. If you don't include this line in all your server push scripts
written in Perl, the output will be buffered and sent to the browser all
at once. For this example, buffering the output would result in all four
HTML pages (the three modified for the guided tour, and the home page)
being sent to the browser after 90 seconds. To the user, it would appear
as though only the home page was reloaded.
The next lines in Listing 8.9
output the multipart/x-mixed-replace parsed header to the Web browser and
start the foreach loop, which loops over each element in the @pages array.
The body of the foreach loop is executed once for each element in the
@pages array. First, the body of the foreach loop prints the parsed header
for that block of data. The next lines should look familiar from the
client pull guided tour example. The explanatory text is placed in the
$guide variable, the file is opened and read into the @template array, the
file is closed, the contents of the @template array are modified, and the
modified contents are then returned to the user's Web browser. Notice how
the variable $_ is used in the following lines from Listing 8.9:
$guide = "<CENTER><HR>$guide_text{$_}<HR></CENTER>";
open(TEMPLATE, "$path/$_") || die "Content-type: text/html\n\nCannot open HTML
files!";
$template[2] = "<TITLE>Guided Tour - $page_names{$_}</TITLE>\n";
The $_ variable is a special Perl variable that in this context takes on
the value of the current array element from the @pages array. For example,
in the first iteration of the foreach loop, the $_ variable is equal to
home.html. In the second iteration it is equal to downloads.html, and in
the final iteration it is equal to tech-support.html. At the end of the
body of the foreach loop, the extra blank line is appended to the data
object and the program sleeps for 30 seconds. This is the delay time to
allow the user time to read the contents of the current page that was just
sent.
Following the foreach loop,
one more body of data is sent with the lines
print "--ThisRandomString\n";
print "Content-type: text/html\n\n";
# Windows users need to change the string "$path/home.html" to
# "$path\\home.html"
open(TEMPLATE, "$path/home.html") || die "Content-type: text/html\n\nCannot open
HTML files!";
@template = <TEMPLATE>;
close(TEMPLATE);
print @template;
print "\n\n";
Then the ending boundary is sent to signal the end of the data being sent.
After the last data block is sent, the guided tour returns the user to the
home page at the end of the tour. The home.html file is opened, the
contents are read into the @template array, and then the contents of the
@template array are sent to the user's Web browser. Running the server
push guided tour produces HTML pages.
Simple Animation
One nice feature of server
push is that you can use it for single images instead of entire documents.
If you place the call to the server push CGI script within the <IMG> tag,
the server can push down new images that replace the previous image. This
creates a flip-book style animation. Flip books are small books that
contain one image per page. The image on each page is only slightly
different than the image on the previous page. When you flip through the
book, the images seem to move; you see a rudimentary animation.
Using this feature of server
push, you can create animations for your Web pages. You just have to
create the image files, place an <IMG> tag in your Web page to call your
animation CGI script, and create a CGI script that pushes down the image
files. For this example, you use the 13 images . These smiley faces are
characters used in the Palace chat software distributed by Time Warner. To
learn more about the Palace software, or to download a free copy of the
Shareware, visit their Web site at http://www.thepalace.com.
After creating all the image
files for your animation, you can create the HTML page in which the
animation will be played. Listing 8.10 contains the HTML code for the
animation.html file (animate.htm if your system limits you to an
eight-character file name and a three-character extension). Notice how the
CGI script is being called from within the <IMG> tag.
With the images created and
the HTML file ready, you just need to create the animate.pl script file.
As with the server push guided tour, the script first needs to send the
multipart/x-mixed-replace header to the Web browser. You do this with the
line
print "Content-type: multipart/x-mixed-replace;boundary=ThisRandomString\n\n";
Listing 8.10: The animation.html File
<HTML>
<HEAD>
<TITLE>Animation Example</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
This animation shows the 13 facial expressions the Palace's default
avatar can use. An avatar is a graphical representation of yourself in
a graphical social environment. The Palace is a 2D graphical social
environment that works on the Internet. For more information about the
Palace, visit their Web site, http://www.thepalace.com.
<CENTER>
<IMG HEIGHT=44 WIDTH=44 SRC="/cgi-bin/animate.pl">
</CENTER></BODY>
</HTML>
|
Next you need a loop to send
the header and data body for each image that is being sent. Because there
are 13 images, you can use a for loop that will execute 13 times. Here is
the for loop for the animation script:
for($i=1 $i<=$num_images; $i++) {
print "--ThisRandomString\n";
print "Content-type: image/gif\n\n";
# Windows users need to change the string
# "$path/$i.gif" to "$path\\$i.gif"
open(GIF, "$path/$i.gif") || die;
(undef, undef, undef, undef, undef, undef,, undef,
$filesize, undef, undef, undef, undef, undef) = stat(GIF);
sysread(GIF, $image, $filesize);
close(GIF);
syswrite(STDOUT, $image, $filesize);
print "\n\n";
sleep 1;
}
The statement
for($i=1 $i<=$num_images; $i++) {
is composed of three parts, the initialization of the loop variable, $i=1;
the loop conditional, $i<=$num_images; and the incrementation of the loop
variable, $i++. The for loops execute until the conditional statement is
no longer true. For this example, the loop variable $i will start at one
and be incremented by one each time the loop executes until it is greater
than the value stored in the $num_images variable. This variable will be
set at the beginning of the animation script file, and will contain the
number of images to be used. Listing 8.11 shows where this variable is
set.
Inside the body of the for
loop, the header and data body for each image file is sent to the user's
Web browser and the script then sleeps for 1 second. The two lines
print "--ThisRandomString\n";
print "Content-type: image/gif\n\n";
print the header for the image being sent to the browser. The lines
# Windows users need to change the string
# "$path/$i.gif" to "$path\\$i.gif"
open(GIF, "$path/$i.gif") || die;
(undef, undef, undef, undef, undef, undef,, undef,
$filesize, undef, undef, undef, undef, undef) = stat(GIF);
sysread(GIF, $image, $filesize);
close(GIF);
syswrite(STDOUT, $image, $filesize);
open the image file, read the contents of the image file into the $image
variable, close the image file, and output the contents of the $image
variable to the user's Web browser. After sending the body of the data,
you need to send the extra blank line and tell the script to sleep for a
second. You do so with the following two lines:
print "\n\n";
sleep 1;
Listing 8.11 contains all the code for the animate.pl script. Notice that
the variables have been set at the beginning and that the ending boundary
is sent to the user's Web browser at the end. You need to change the $path
variable to be valid for your system. Also, Windows users should remove
the first line of the code and change the string in the open statement.
Listing 8.11: The animate.pl Script
#!/usr/local/bin/perl
# All users need to change the $path variable to a valid
# path for their system. Windows users need to use a
# path in the form $path = "c:\\robertm\\gifs";
$path = "/users/robertm/gifs";
$num_images = 13;
$|=1;
print "Content-type: multipart/x-mixed-
replace;boundary=ThisRandomString\n\n";
for($i=1 $i<=$num_images; $i++) {
print "--ThisRandomString\n";
print "Content-type: image/gif\n\n";
# Windows users need to change the string
# "$path/$i.gif" to "$path\\$i.gif"
open(GIF, "$path/$i.gif") || die;
(undef, undef, undef, undef, undef, undef,, undef,
$filesize, undef, undef, undef, undef, undef) = stat(GIF);
sysread(GIF, $image, $filesize);
close(GIF);
syswrite(STDOUT, $image, $filesize);
print "\n\n";
sleep 1;
}
print "--ThisRandomString--\n\n";
|