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

Hi. I am trying to make a refresher page that points to a CGI script. What I have below works fine. However, because I am trying to make this part of a module, I would like to insert the actual code for test.cgi in the script tag instead of the link to the test.cgi script. Is there anyway to do this?

Thanks,

jim



open REFRESH,">$refreshFile" or die "Couldn't open $refreshFile"; print REFRESH "<meta http-equiv=\"Refresh\" content=\"$refreshTime; UR +L=$refreshUrl\">"; print REFRESH "<meta http-equiv=\"Pragma\" content=\"no-cache\">"; print REFRESH $q->start_html('-title'=>'Analysis in Progress','-bgcolo +r'=>'eeeeee'); print REFRESH "<SCRIPT src='http://www.test.com/cgi-bin/test.cgi></SCR +IPT>"; close REFRESH; print "Location: $refreshUrl\n\n";

2001-10-23 Edit by Corion: Added CODE tags

Replies are listed 'Best First'.
Re: Inserting CGI code in script tag
by Arguile (Hermit) on Oct 23, 2001 at 19:47 UTC

    Consistancy

    Mixing your metaphors, ie. using CGI OO with flat HTML interpolation can get really messy and confusing. You might consider sticking with one, or even better use a templating system if you'll be doing multiple different pages.

    These are my favourites (there are many other systems as well):

    Here Docs

    print <<"HTML"; This is what's called a here doc. HTML

    Anything between the <<LABEL and the end LABEL, which must be on a line all by itself, will be interpretted as a string. You don't have to worry about quoting conventions. A straight here doc is like single quoting in Perl ('), but if you add the double quotes around the first label (") perl will interpolate your variables (substitute them).

    select()

    select REFRESH; print "Test";

    "Test" will now be printed to the REFRESH handle. When you select a handle it becomes the active handle. Click the link for more info, and remeber to reset it when you're done!.

    See Also

Re: Inserting CGI code in script tag
by Boldra (Curate) on Oct 23, 2001 at 22:05 UTC
    Your question is confusing.

    You code clarifies it a little, but you would do well to take Arguile's good advice.

    My guess is that you have two misunderstandings:
    • <SCRIPT></SCRIPT> tags instruct the browser to execute javascript (or M$ equivalent), not perl
    • It is possible to print HTML directly to the browser instead of printing to a file and redirecting to that file.
    Given the second point, you may want to consider redirecting to a perl program which prints the 'Analysis in Progress' message in a refreshing HTML document until the background task is complete.
    eg.
    if(&ready) { &redirect_to_results; } else { print &wait_page_html; }
    where &ready might look for the existance of a file on the server indicating that the background task is complete.

    Of course, I may have completely misunderstood the question
    - Boldra
Re: Inserting CGI code in script tag
by dmmiller2k (Chaplain) on Oct 24, 2001 at 00:30 UTC

    I agree with both Arguile and Boldra in that your question is slightly confusing.

    It appears that what you are trying to do is to redirect to another CGI script ('test.cgi') from your script, of which you've presented a fragment. To do this using CGI.pm, you merely have to:

    print $q->redirect($refreshUrl);

    This sends an HTTP header which has the same effect as putting the following line into the header of an HTML page (hence the name, "HTTP-EQUIV"):

    <META HTTP-EQUIV="Refresh" CONTENT="$refreshTime; URL=$refreshUrl">

    Your script fragment does precisely the same thing in its last line (which prints the Location: header). In fact, you could get rid of all the other print statements to the same effect.

    What's confusing is the relationship between $refreshFile and $refreshUrl. If you meant $refreshUrl to refer to the same file, the one you are creating on the fly, your file would be redirecting to itself in an endless loop.

    BTW, the URL in the <SCRIPT> tag (src='http://www.test.com/cgi-bin/test.cgi') should refer to a javascript file, e.g., 'something.js', NOT to a perl script (unless that perl script is a CGI program that writes pure javascript code to its standard output).

    Any code between the <SCRIPT> and </SCRIPT> tags ought to be javascript as well.

    In either case, the javascript code executes at the BROWSER, not on the server.

    dmm

    
    You can give a man a fish and feed him for a day ...
    Or, you can teach him to fish and feed him for a lifetime
    
      Sorry about the confusing post. I only put in a fragment of the code and that is where some of it arises from. Essentially I have a module that does the following:

      Takes a subroutine as an argument (usually one that takes a long time to run)

      Forks off a child to process the subroutine code while the parent creates a temporary "analysis in progress" html page (that refreshes every so often). When the child is finished executing it creates another html page that prints any output from the subroutine, and then overwrites the "analysis in progress" page with the content of this page thus ending the refresh.

      I get tired of looking at that screen and wanted to give some kind of progress update and incorporate it into the module. So, in addition to the subroutine used to perform the actual work, I want to take another subroutine as an argument that can be used to give some kind of status on the update. In my case I wanted it to print the number of records that have been inserted into a db of the total number using some DBI code. What I could do with the second subroutine is create a temporary CGI fine that the refresher page redirects to. However, I was hoping to just be able to have the progress subroutine print to the browser directly, that is without needing to generate this temporary cgi file. That is the basis of my question. There may be a much easier way to do this, I am not sure. I hope this makes things clearer.

      Also, I was using the script tag to point to the cgi program for historical reasons. The cgi script outputs document.write commands so that part of the script is fine. However, I should just use the redirect as it is easier.

      Thanks again.

      -jim

        The problem with this kind of thing in general is that the web is request/response based. Server-push (that is, having the progress subroutine print to the browser directly) is difficult to get right.

        I've had some success with a similar problem by storing the process id of the forked process (or some other identifying value) in a session record (perhaps in a database table), and passing the key to that session record as a parameter to a progress script (e.g., "test_progress.cgi?session_key=whatever"). The progress script can then use the session key to look up the process id (or whatever), check whatever it needs to check, and regenerate the "in progress" page with a redirect to itself after some amount of time.

        When the process is complete, the progress script can immediate redirect to a third script (or perhaps the original one, with a different parameter to identify the new context) for display of the output, which must have been stored somehow by the forked process, in a location identifiable by the same session key--I often use a generated filename in /tmp, with the hostname and process ID of the background process somehow incorporated in the filename, as the session key.

        There can be irritating reliability (i.e., timeout) problems with your original idea of rewriting the page from the forked process. It may or may not work, depending upon how long the background process takes and other factors beyond your control, such as browser dependencies, server-side loading, etc., and whether or not the progress page itself contains </BODY> and </HTML> tags.

        dmm

        
        You can give a man a fish and feed him for a day ...
        Or, you can teach him to fish and feed him for a lifetime
        
Re: Inserting CGI code in script tag
by Tetramin (Sexton) on Oct 24, 2001 at 01:06 UTC
    If test.cgi produces javascript then
    print REFRESH "<SCRIPT><!--\n"; my $oldfh = select(REFRESH); require "test.cgi"; select $oldfh; print REFRESH "//--></SCRIPT>";