tags:

views:

449

answers:

6

What should you call after printing HTML from a Perl CGI script? I have seen empty return statements, exit statements, and in some cases nothing at all. Does it matter?

#!perl

print "Content-type: text/html\n\n";
print <<'END_HTML';
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<title>Hello world!</title>
</head>
<body>
    <h1>Hello world!</h1>
</body>
</html>
END_HTML

# do anything else here?
# return;
# exit;

Update

Let's suppose you have some tests where you are printing HTML that isn't at the very end of the file. In this case is it more clear to call exit or return to visually show that the script should end at that time? I know this isn't the best way to write this--please just take this at face value for the sake of the question.

#!perl

use CGI;
my $q          = CGI->new();
my $action     = $q->param('action');

my $html_start = "Content-type: text/html\n\n";
$html_start   .= <<'END_HTML';
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<title>Hello world!</title>
</head>
<body>
END_HTML

my $html_end = <<'END_HTML';
</body>
</html>
END_HTML

if ($action eq 'foo') {
    print $html_start;
    print '<p>foo</p>';
    print $html_end;
    # do anything else here?
}
else {
    print $html_start;
    print '<p>bar</p>';
    print $html_end;
    # do anything else here?
}
+1  A: 

No, it doesn't matter. I always let the script die by itself instead of 'return;' or 'exit;' since there's no need for either of those statements (in the end of a perl document that is) and it's the same thing as 'exit;' or 'exit 0;'.

Björn
+3  A: 

I guess this is more a question about coding style than functionality. If you have a simple, straightforward program, with no branching, there is little reason to mark the termination of the program by anything special:

  • return is not going to return anything that anybody can use, since your program ends here
  • exit is just going to exit with status 0, which would happen naturally anyway

However, if the structure is more complex, I would advise to mark the termination point by something specific, to signal to someone who reads your code that, for that defined set of conditions, there is nothing to take into account there anymore.

I would use exit rather than return, for the simple reason that return can be mistaken for the end of a sub, whereas exit very specifically states that the program terminates at this point.

Varkhan
This was a simplified example. Let's say you have a bunch of tests and you are redirecting based on the result of the test. Is it enough to see print "Location: foo.pl\n\n"; and know that's the end of the script in that particular test? I can elaborate in the question if this isn't clear.
cowgod
Please elaborate a bit on the structure of your code. If you have a bunch of different cases, where you can terminate before the physical end of the file, IMO you should include some termination marker, preferably exit...
Varkhan
Question updated.
cowgod
Answer updated ;)
Varkhan
A: 

it makes sense that you don't necessarily have to return or exit if it is a stand-alone thing. but what if this snippet is from within a function? would it still apply? would return or exit be preferred for some reason? is it still just styling?

Rayjan
+3  A: 

You should always print out "\n\n" at the end of your output to tell the webserver the output is finished. Apache may do this for you on successful script termination.

If your script is finished, you should technically call "exit" with the appropriate exit status-- zero for success, nonzero for errors. The webserver inspects the exit status and renders the appropriate page (error code 500 is typical if the exit status shows anything other than success). If you don't specify a "return" value or call exit directly, Perl (in this case) will assume successful termination and the webserver will treat your CGI script the same as if you called "exit(0)".

This is all described in the CGI specification (RFC 3875 is current, IIRC).

Rick C. Petty
You don't need to print a double newline at the end of the output. That's only to separate the header from the body.
brian d foy
+1  A: 

I would recommend return instead of exit so that if you switch to CGI::Fast you can just turn it into a sub.

Paul Tomblin
A: 

To answer your "updated" question: In my current application, I use common methods to do something like this:

# UI.pm
package UI;

sub top    { print "<html><head><title>$_[0]</title><body>"; }
sub bottom { print "</body></html"; }

# All the individual .cgi files
package main;

UI::top('Welcome to my page');
print "<p>Welcome to my page!</p>";
UI::bottom();

If you're feeling adventurous, you could hook BEGIN and END to do this automatically, but I wouldn't - I think it'd be too much fiddling around for a fairly minor benefit.

This isn't how I'd do it now, if I had to do it all over: I'd rely more on some sort of middle layer such as Catalyst, which would allow me to move up quickly to mod_perl or back to CGI. Or even better, write my application from the ground-up to use more AJAX - that way, most of my "actions" are carried out by really small Perl scripts which just process the input and respond back to the Javascript application in text/plain or text/json.

Gaurav