Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Emulate CGI "server push" to show real time status of CGI script for all browsers

by hackdaddy (Hermit)
on Sep 30, 2003 at 23:14 UTC ( [id://295471]=perlquestion: print w/replies, xml ) Need Help??

hackdaddy has asked for the wisdom of the Perl Monks concerning the following question:


Hi. For a CGI script I am creating on Apache/Win32, I need to emulate CGI "server push" to show real time status of CGI script by logging progress to the client. As the CGI script runs, I need to show to the user what the script is doing. I need to support all browsers: IE, Netscape, and Opera.

I would like to be able to update the contents of a textarea dynamically. Is is possible using hidden frames and Javascript? What is Javascript stream-emulation?

IE does not support CGI server push and so I need to use a technique that will work for all browsers.

Are there CGI widgets I could use for this purpose? Any modules or tools I am overlooking?

The real problem is that I am using WWW::Mechanize to automate other web sites from the script. I do not want the client to time-out waiting for the CGI script to complete. How do I keep-alive the Client connection to never let the user see a time-out? I also do not want to slow down the scripts by creating a lot of traffic. I am currently using using POE::Component::Client::HTTP to simultaneously check the response times of all the web sites I will automate. My manager does not want the user to think the script has hung or is not responding.

I am also looking into using LWP::Parallel::UserAgent. Is LWP or WWW::Mechanize thread-safe for using 5.8.0 threads? Is threading on CGI worth the effort?

Any help is appreciated. Thanks.

Hackdaddy

Replies are listed 'Best First'.
Re: Emulate CGI "server push" to show real time status of CGI script for all browsers
by jonadab (Parson) on Sep 30, 2003 at 23:37 UTC

    Most browsers support the HTTP refresh, and for those that don't you can put a "Next" link at the bottom. Your whole page will reload for each update, and the script will run once for each update, but it's possible to support a wide range of browsers this way. It does place an extra burden on the script, which has to be able to pick up where it left off each time the browser reloads the page, but this is doable. The other option is to use scripts or plugins to communicate with the server and get information from a server process; this will allow for smoother updates but will support fewer browsers.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
      I second the suggestion of using HTTP refresh. It was the only way I found to reliably update data on various browsers (IE being particularly crappy about server-push).

      My strategy is to spawn a background process that does the time-consuming work while redirecting the browser to a progress page. The background process periodically writes to the progress page. You can even change the refresh time in the meta tag on the progress page if you have an idea of how long you expect different steps in the processing to take.

      A tip I can pass along about doing this, when forking off a child process in a cgi script, make sure to close STDOUT and STDERR in the child or the browser will wait for the child to complete.

        I did exactly this for my CGIBurn application. Source code is there if you'd like to poach ideas; the code itself is GPL'd.
        IE being particularly crappy about server-push.

        IE does not support Server-Push.

Re: Emulate CGI "server push" to show real time status of CGI script for all browsers
by cLive ;-) (Prior) on Oct 01, 2003 at 02:42 UTC
    Depends how long you expect the task to take. I used to use something like this (which I'm sure you can update now that browsers have advanced and the DOM has stabalized a lot more :):
    #!/usr/bin/perl use strict; use warnings; use CGI; # unbuffer output $|++; print $q->header(). $q->start_html. $q->start_form({-name=>'statusform'}). $q->textfield('status','',50,50). $q->end_form; for (0..100) { print_status("$_\% completed"); sleep(1); } print $q->end_html; exit(0); sub print_status { my $status = $_[0]; $status =~ s/'/\\'/g; print $q->script({-language=>'javascript'}, "document.statusform.status.value = '$status'\n" ); }
    This is only off the top of my head and I haven't tested, but that's the rough idea. It's a bit of a hack, but I remember getting it to work in IE and Netscape (but that was 3yrs ago - there's probably a more acceptable method used today. Probably :)

    Looking at it it now, I'd probably use an iframe with the above hack and js page refresh every 30 seconds to avoid getting too big a page of js.

    .02

    cLive ;-)

Re: Emulate CGI "server push" to show real time status of CGI script for all browsers
by Beechbone (Friar) on Oct 01, 2003 at 16:48 UTC
    The most simple way would be to output just text. If your output it delayed (and don't forget to flush()) almost all browsers will display it as it comes in.

    Just don't put the text into a table. A div with postitioning information (overlay the older messages) should be ok, and should also work for older browsers that will ignore the div-tag.

    print "Content-Type: text/html\n\n"; print "<html><body><h1>This will take some time...</h1>"; my $i = 10; while ($i) { print "<p>Please wait, working for $i second(s)...</p>"; $i--; } print "<hr><p>DONE! finally...</p></body></html>";

    BTW: To keep-alive a connection, just write a NULL byte out every now and then. Or something else...

    print "<!--"; while ($working) { print ".";
    or:
    while ($working) { print "\00" ;
    Search, Ask, Know
Re: Emulate CGI "server push" to show real time status of CGI script for all browsers
by Anonymous Monk on Oct 02, 2003 at 17:40 UTC
    Use an IFRAME in the page that points to a status.cgi script with a <meta http-equiv="refresh" content="2; URL=..."> tag. This way you don't push, all browsers support IFRAMEs now (I think), and you don't have to refresh the whole page with each GET.
      He apparently didn't read the whole thread :)
Re: Emulate CGI "server push" to show real time status of CGI script for all browsers
by rustycar (Novice) on Jul 23, 2008 at 16:03 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://295471]
Front-paged by krisahoch
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-03-29 02:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found