CGI::Application::Plugin::Streaming does not really provide what I need. I am not trying to stream a static file from disk. Instead, I am trying to write a run mode that dynamically generates HTML content and display each line of this dynamically generated content as soon as it becomes available.
But your post inspired me to try the following hack: stream the content of a temporary file, and print the dynamically generated HTML lines to that temp file.
It doesn't seem to work, as illustrated by the following piece of code:
#!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(':al
+l');
}
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 dynamical
+ly streamed to scean');
print TEMP_HTML_FILE $q->h3('HTML page dynamically streamed to sce
+an');
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 "<a href=\"$script_name?dlg=stream_dynamic_ht
+ml\">Stream dynamic HTML page</a><br/>\n";
print TEMP_HTML_FILE "<a href=\"$script_name?dlg=stream_static_fil
+e\">Stream static file</a><br/>\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 CgiappStreamingWi
+thAuthentication!');
my $user_name = $self->authen->username;
$output .= $q->h3("Hello, '$user_name'");
$output .= $q->p()."\n";
$output .= "<a href=\"$script_name?dlg=stream_dynamic_html\">Str
+eam dynamic HTML page</a><br/>\n";
$output .= "<a href=\"$script_name?dlg=stream_static_file\">Stre
+am static file</a><br/>\n";
$output .= $q->end_html();
return $output;
}
1;
|