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

My boss wants me to hook up a gizmo which sends a response (e.g., "Still processing...") back to the browser while a SQL query is running. The purpose of this message would be to stop the browser from timing out.

Sounds like a job for the CGI::Push module. The problem is that, according to its documentation "Only Netscape Navigator supports server push. Internet Explorer browsers do not."

Now what? Do I have to hobble something non-Perlish together on the client side, or is there some nice Perl CGI-related module already written that will duplicate server push for IE browsers?

  • Comment on CGI::Push Only Works With Netscape. Now What?

Replies are listed 'Best First'.
Re: CGI::Push Only Works With Netscape. Now What?
by merlyn (Sage) on Sep 19, 2001 at 21:58 UTC
      Thanks for all the help, people. In order not to violate Merlyn's copyright I am not going to repost his code here, but I wonder whether perhaps his article contains a typo. Line 55 reads
      "=55= my $out = IO::File->new($DIR_html,"w") or
      Shouldn't this line actually be
      "=55= my $out = IO::File->new($URL_html,"w") or
      If someone could verify the correct code for me I would appreciate it.
        No, $URL_html is the view from the browser. You're doing a unix file open, so it needs to be the view from the Unix side, $DIR_html. That's explained in the column. You did read the column, right?

        -- Randal L. Schwartz, Perl hacker

Re: CGI::Push Only Works With Netscape. Now What?
by Hero Zzyzzx (Curate) on Sep 19, 2001 at 21:48 UTC

    You could unbuffer output by setting "$|=1;" at the top of your script, and then print something to STDOUT right before your query executes. The browser will then wait for the rest of the page to be printed while your query is executing.

    I have a script that crunches images with Image Magick that reports on progress to the user picture-by-picture. This method works EXCELLENT in IE, not too sure about netscape.

    Make sure the "unbuffered", incremental output isn't contained in table- Tables won't render until the whole thing downloads.

    You're probably going to have to play with this, I think it works differently in different browsers.

    --Psuedo Code -- #!/usr/bin/perl -wT use strict; use CGI; my $q=CGI->new(); $|=1; print $q->header(); # print all your other HTML stuff for the header type thingy, only com +plete tables my $query=$dbh->prepare($your_query) or die("Couldn't prepare: ".$dbh- +>errstr()); print "Still Processing"; $query->execute() or die("Couldn't execute: ".$dbh->errstr()); print $query_results_and_bottom_of_page;

    -Any sufficiently advanced technology is
    indistinguishable from doubletalk.

Re: CGI::Push Only Works With Netscape. Now What?
by maverick (Curate) on Sep 19, 2001 at 21:56 UTC
    Here's an alternate approach, pehaps a bit complex, but it would get you around having to have 'push' at all. I assume you have some sort of session tracking mechanism already in place.

    • Have the script that runs the long query just return a page with a meta-refresh of X seconds, while it forks and runs the long query in the background. The child process then stores the results in a session specific location (maybe use Apache::Session).
    • The script that the meta-refresh points to checks the session store to see if the results are there. If they are, they are given to the browser, and removed from the session store. If not, the same meta-refresh page is returned to the browser and the process repeats until the long query is complete.


    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

Re: CGI::Push Only Works With Netscape. Now What?
by andreychek (Parson) on Sep 19, 2001 at 21:47 UTC
    What I'm assuming here is that the browser made a request, and is sitting there waiting for a response. During that wait, your SQL query is running.

    If thats the case -- perhaps you could send the browser, say, and HTML comment.. or something else trivial, which won't affect the display, but allow the browser to know something is still going on, and that it shouldn't time out. You can just set up some sort of loop, or even use the alarm function, and have your script send something to the browser every 10 seconds or so

    While all that is taking place, you could use a Javascript window.status call to put your "Still Processing" message on the bottom of the status bar. Just a thought.. Good Luck!
Re: CGI::Push Only Works With Netscape. Now What?
by duckyd (Hermit) on Sep 20, 2001 at 02:35 UTC
    here's a really simple way to do what you want: have the inital request for the search return a simple page that says "Please be patient while results are obtained" or whatever. That page should have a meta refresh set for a short amount of time (1 second or a fraction of a second) to the exact same url as the original request (or including the same parameters as hidden if the original parameters were not in the url) but with a flag set that indicates the results should be sent rather than the "wait" page. This page must be *unbuffered* - that is, it should not return *anything* at all until the search is complete. This way, the browser sits spinning and the user sees the "wait" page until their results are ready. hope this helps