Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^2: CGI::Application... flushing output to browser?

by alain_desilets (Beadle)
on May 04, 2012 at 03:37 UTC ( #968851=note: print w/ replies, xml ) Need Help??


in reply to Re: CGI::Application... flushing output to browser?
in thread CGI::Application... flushing output to browser?

I too face this problem, and tried your hack above.

It works as long as I don't have to use the Authentication plugin. With Authentication plugin, it seems that any irregular mode that is protected by the plugin can never be displayed. Whenever you try to go to that mode, you get the login box, and even if you enter the right credentials, you get to the login box again.

I haven't quite figured out why yet, but I think it's because session state is transmitted by cookies, which themselves are transmitted through http headers. And the specific cookie headers generated by Authentication plugin are not available until AFTER the body has been generatied (the cookie headers are being generated by a postrun hook for some strange reason). In a standard runmode that doesn't matter, because the headers are prepended to the body before the whole thing is outputted. But with an irregular mode, you need to generate and print the headers before you generate and print the body.

Has anybody solved this problem?


Comment on Re^2: CGI::Application... flushing output to browser?
Re^3: CGI::Application... flushing output to browser?
by Anonymous Monk on May 04, 2012 at 09:36 UTC

      Sorry about that. See below. It's a bit long, but it's a complex issue, and I can't find a shorter way of expressing all the things I have tried.

      package SimpleApp; use base 'CGI::Application'; use strict; ################################################################### # # This script is an attempt at "subverting" CGI::Application into # running modes that print HTML directly to STDOUT, instead of # cumulating it into a string and returning it. # # It seems possible to do that, as long as you don't use the # Authentication plugin, as illustrated below. # # In this App, we have two versions of each of the run modes. # # The 'print_at_very_end' version implements the standard # CGI::Application # approach, namely, it collects the HTML output in a string # variable, and returns it. # # The 'print_as_you_go' version prints the HTML directly to # STDOUT, as soon as it is generated. These versions of the run # modes need to print headers themselves instead of letting # CGI::Application, because the later generates the headers AFTER # the body method has been called (and it prepends them to the body +). # But by that time, it's too late to print the headers, because # the body has already been printed to STDOUT. # # To switch between the 'print_as_you_go' and 'print_at_very_end' # versions, simply set $print_when to 'at_very_end' or 'as_you_go'. # # You can also run the application with, or without Authentication plu +gin. # Simply set $use_authentication to 1 or undef; # # Try the following scenarios. # # Scenario 1: 'print_at_very_end', with authentication # - Set $print_when = 'at_very_end' and $use_authentication = 1 # - Clear cookies # - go to simple_app.cgi # - login as u=guest, p=1234 # - notice how the Welcome page takes about 2 secs before it displays # anything (because it sleeps for 1 sec between generating each line + # and doesn't print anything until all the lines have been generated +) # - click on Help link # - notice how you're brought to the Help page without being asked # to login again # # Scenario 2: 'print_as_you_go', without authentication # - Set $print_when = 'as_you_go' and $use_authentication = undef # - Clear cookies # - go to simple_app.cgi # - no need to login (there is no authentication) # - notice how the content of the Welcome page starts being displayed # immediatly, without the 2 secs delay. # - click on Help link # - notice how you're brought to the Help page without being asked # to login again. # # Scenario 3: 'print_as_you_go', with authentication # - Set $print_when = 'as_you_go' and $use_authentication = 1 # - Clear cookies # - go to simple_app.cgi # - login as u=guest, p=1234 # - notice how the content of the Welcome page starts being displayed # immediatly, without the 2secs delay. # - click on Help link # - notice how you're asked to login again. # - login again as u=guest, p=1234 # - Notice how you are brought to the Welcome page again, # as opposed to the Help page you were trying to go to. # - This seems to be due to the fact that the session cookies # were not output correctly (they are part of the headers, # and we are mocking around with them in non-standard ways.) # ################################################################### my $print_when; BEGIN { # #$print_when = 'at_very_end'; $print_when = 'as_you_go'; my $use_authentication = 1; # my $use_authentication = undef; if ($use_authentication) { use CGI::Application::Plugin::Authentication; SimpleApp->authen->config( DRIVER => [ 'Generic', { guest => '1234'} ], POST_LOGIN_RUNMODE => 'welcome', LOGOUT_RUNMODE => "logout" ); SimpleApp->authen->protected_runmodes(':all'); } } sub setup { my $self = shift; $self->start_mode('welcome'); $self->run_modes( 'welcome' => "welcome_print_$print_when", 'logout' => "logout_print_$print_when", 'help' => "help_print_$print_when", 'strea_file' => "stream_file" ); $self->mode_param('dlg'); } sub welcome_print_as_you_go { my $self = shift; $self->header_type("none"); $| = 1; print $self->query()->header(); # Get CGI query object my $q = $self->query(); print $q->start_html(-title => 'Welcome to SimpleApp!'); my $user_name = $self->authen->username; print $q->h3("Hello, '$user_name'"); my $sleep_for = 1; print $q->p("The next few lines will be printed at $sleep_for sec +s intervals."); for (my $ii=0; $ii < 2; $ii++) { print "Line $ii<br/>\n"; sleep($sleep_for); } print $q->p()."\n"; print "<a href=\"simple_app.cgi?dlg=help\">Help</a><br/>\n"; print "<a href=\"simple_app.cgi?authen_logout=1\">Logout</a><br/> +\n"; print $q->end_html(); return ''; } sub welcome_print_at_very_end { my $self = shift; # Get CGI query object my $q = $self->query(); my $output = ''; $output .= $q->start_html(-title => 'Welcome to SimpleApp!'); my $user_name = $self->authen->username; $output .= $q->h3("Hello, '$user_name' (print as batch)"); my $sleep_for = 1; $output .= $q->p("The next few lines will be printed at $sleep_fo +r secs intervals."); for (my $ii=0; $ii < 2; $ii++) { $output .= "Line $ii<br/>\n"; sleep($sleep_for); } $output .= $q->p()."\n"; $output .= "<a href=\"simple_app.cgi?dlg=help\">Help</a><br/>\n" +; $output .= "<a href=\"simple_app.cgi?authen_logout=1\">Logout</a +><br/>\n"; $output .= $q->end_html(); return $output; } sub logout_print_at_very_end { my ($self) = @_; # Get CGI query object my $q = $self->query(); my $output = ''; $output .= $q->start_html(-title => 'You have been logged out!'); $output .= $q->h3("You have been logged out."); $output .= $q->p()."\n"; $output .= "<a href=\"simple_app.cgi?dlg=welcome\">Home</a><br/> +\n"; $output .= "<a href=\"simple_app.cgi?dlg=help\">Help</a><br/>\n" +; $output .= $q->end_html(); return $output; } sub logout_print_as_you_go { my ($self) = @_; $self->header_type("none"); $| = 1; # Get CGI query object my $q = $self->query(); print $self->query()->header(); my $output = ''; print $q->start_html(-title => 'You have been logged out!'); print $q->h3("You have been logged out."); print $q->p()."\n"; print "<a href=\"simple_app.cgi?dlg=welcome\">Home</a><br/>\n"; print "<a href=\"simple_app.cgi?dlg=help\">Help</a><br/>\n"; print $q->end_html(); return $output; } sub help_print_as_you_go { my ($self) = @_; $self->header_type("none"); $| = 1; my $q = $self->query(); print $q->header(); print $q->start_html(-title => 'SimpleApp Help'); my $user_name = $self->authen->username; print $q->h3("Dear '$user_name', how may I help you? (print as yo +u go)"); print "<a href=\"simple_app.cgi?dlg=welcome\">Home</a><br/>\n"; print "<a href=\"simple_app.cgi?authen_logout=1\">Logout</a><br/> +\n"; my $sleep_for = 1; print $q->p("The next few lines will be printed at $sleep_for sec +s intervals."); for (my $ii=0; $ii < 2; $ii++) { print "Line $ii<br/>\n"; sleep($sleep_for); } print $q->end_html(); return ''; } sub help_print_at_very_end { my $self = shift; # Get CGI query object my $q = $self->query(); my $output = ''; $output .= $q->start_html(-title => 'SimpleApp Help'); my $user_name = $self->authen->username; $output .= $q->h3("Dear '$user_name', how may I help you? (print +as batch)"); my $sleep_for = 1; $output .= $q->p("The next few lines will be printed at $sleep_fo +r secs intervals."); for (my $ii=0; $ii < 2; $ii++) { $output .= "Line $ii<br/>\n"; sleep($sleep_for); } $output .= $q->p()."\n"; $output .= "<a href=\"simple_app.cgi?dlg=welcome\">Home</a><br/> +\n"; $output .= "<a href=\"simple_app.cgi?authen_logout=1\">Logout</a +><br/>\n"; $output .= $q->end_html(); return $output; } sub stream_file { my ($self) = @_; } 1; # Perl requires this at the end of all modules

        Hmm, regarding buffering/autoflush/$|=1, adding  eval { Apache2::RequestUtil->request->rflush; }; before sleep works for me

        but according to the docs  local $|=1 should have also worked, but I don't have the latest mod_perl2/apache2 here :/

        Regarding the missing cookies, I fear you're right , the module definitely needs updating , bummer :(

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://968851]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (10)
As of 2014-10-23 11:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (125 votes), past polls