#!perl
#
###########################################################
# This script is an attempt at creating a cgiapp run mode
# that dynamically generates HTML lines, and displays them
# as soon as they are available. This in contrast
# to the standard cgiapp mode where the HTML content is
# returned in bulk by the run mode, and cgiapp prints it
# all in one go, at the very end of the transaction.
#
# This particular attempt uses the CGI::Application::Plugin::Streaming
# plugin to stream the dynamically created content to STDOUT.
#
# It's implemented by the stream_dynamic_html() method, which
# does the following:
#
# - Opens a temporary HTML file
# - invokes the stream_file() method on it
# - Prints the dynamically generated HTML content to the temp file
# - Closes the file.
#
# As it turns out, this does not work for two reasons
#
# a) Invoking stream_file() on a file that is still open
# and being written to does not work. Instad of
# receiving an HTML file with the content, the browser
# receives the streammed content as a text file
# which only contains the single digit 1. If I try to
# write the complete HTML content to the temp file,
# then close it and start the file_stream(),
# then I get the full HTML content, but this content
# is not being displayed as you go. It only becomes
# available in bulk at the end of the transaction.
#
# b) stream_file() does not actually display the HTML
# file's content as a page. Instead, it sends it to the
# browser as a "file" to be saved to disk or opened with
# an appropriate application
#
# To try the code:
# - Create a script cgiapp_streaming_with_authentication.cgi which
# runs the CgiappStreamingWithAuthentication app.
# - Set $fpath_to_stream and $temp_dynamic_html_fpath
# to pathes on your system, which can be written to by
# your web server.
# - Clear cookies
# - Load cgiapp_streaming_with_authentication in your
# browser
# - Login as u=guest, p=1234
# - Click on the 'Stream static file' link
# => This will download a text file and ask you to save it
# to disk, or open it.
# - Click on 'Stream dynamic HTML page' link.
# => - This will download a file called
# streamed_dynamic_content.html
# (whose content is generated dynamically), and ask
# you to save it to disk, or open it.
# - Notice how it takes a few seconds before it
# prompts you to open or save the file (because
# the script that generates the HTML content sleeps
# for one second after each line it prints to the
# temp file).
#
# - Notice how the file does not contain the HTML code
# generated by stream_dynamic_html(). It only
# contains the single digit 1.
###########################################################
use strict;
use warnings;
package CgiappStreamingWithAuthentication;
use base 'CGI::Application';
my $script_name = 'cgiapp_streaming_with_authentication.cgi';
my $fpath_to_stream = '/hello.txt';
my $file_type = 'text/plain';
my $temp_dynamic_html_fpath = '/streamed_dynamic_content.html';
use CGI::Application::Plugin::Stream (qw/stream_file/);
my $use_authentication = 1;
if ($use_authentication) {
use CGI::Application::Plugin::Authentication;
CgiappStreamingWithAuthentication->authen->config(
DRIVER => [ 'Generic', { guest => '1234'} ],
POST_LOGIN_RUNMODE => 'welcome',
LOGOUT_RUNMODE => "logout"
);
CgiappStreamingWithAuthentication->authen->protected_runmodes(':all');
}
sub setup {
my $self = shift;
$self->start_mode('welcome');
$self->run_modes(
'welcome' => "welcome",
'stream_static_file' => "stream_static_file",
'stream_dynamic_html' => "stream_dynamic_html",
);
$self->mode_param('dlg');
}
sub stream_dynamic_html {
my ($self) = @_;
$| = 1;
open TEMP_HTML_FILE, ">$temp_dynamic_html_fpath";
my $q = $self->query();
print TEMP_HTML_FILE $q->start_html(-title => 'HTML page dynamically streamed to scean');
print TEMP_HTML_FILE $q->h3('HTML page dynamically streamed to scean');
print TEMP_HTML_FILE $q->p("The following lines will be printed at 1 sec interval.");
for (my $ii=0; $ii<3; $ii++) {
print TEMP_HTML_FILE $q->p("This is line $ii.\n");
sleep(1);
}
print TEMP_HTML_FILE $q->p()."\n";
print TEMP_HTML_FILE "Stream dynamic HTML page
\n";
print TEMP_HTML_FILE "Stream static file
\n";
print TEMP_HTML_FILE $q->end_html();
close TEMP_HTML_FILE;
$self->stream_file($temp_dynamic_html_fpath, 10);
}
sub stream_static_file {
my ($self) = @_;
$| = 1;
$self->stream_file( $fpath_to_stream, 10);
}
sub welcome {
my $self = shift;
# Get CGI query object
my $q = $self->query();
my $output = '';
$output .= $q->start_html(-title => 'Welcome to CgiappStreamingWithAuthentication!');
my $user_name = $self->authen->username;
$output .= $q->h3("Hello, '$user_name'");
$output .= $q->p()."\n";
$output .= "Stream dynamic HTML page
\n";
$output .= "Stream static file
\n";
$output .= $q->end_html();
return $output;
}
1;