#!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;