[DRAFT 1.3] Perl CGI FAQ(s)

This issue is now closed.

Modifications along the lines proposed were adopted into the development version of perlfaq9 at revision 1.2.

I leave this web page for historical interest.

The 5-minute trial argument

[Perl FAQ part 9 (perlfaq9) refers]

I am a great fan of Usenet FAQs, and have every respect for those who take the time and trouble to draft them. The standard Perl FAQs have been a "mine of information" that I, for one, have been glad to use and to refer others to.

One of the existing articles in the Perl FAQ part 9, the one about "redirecting to another page", seems to me to still contain discrepancies and to be potentially somewhat misleading, and the purpose of this page is to propose an alternative version and to supply justification for this alternative. This existing FAQ entry actually also contains information about the format of any CGI response. This seems the wrong place for it, and if it is considered appropriate for it to appear at all (which I think it is, as there is some Perl-related content to it, namely the newline representation), then IMHO it needs an extra FAQ entry to deal with it.

The alternative approach would be to tell Perl programmers that discussions of the CGI are off-topic for the Perl programming language, to refer them to appropriate resources, to counsel them to use CGI.pm instead of trying to knit their own, and then to omit all detail of the CGI response formats as being irrelevant at that level. Discussion on c.l.p.misc seemed to favour keeping a certain amount of under-the-covers detail, however, and the draft has gone along with that view.

The item as it had been in Perl FAQ part 9 (perlfaq9)

This now exhibits the FAQ9 item in the form in which it appears in the 5.7.2 package (i.e the development version at the time of writing this discussion-page version) - the FAQ part carries the heading:

perlfaq9 - Networking ($Revision: 1.26 $, $Date: 1999/05/23 16:08:30 $)

and the entry reads as follows:

How do I redirect to another page?

According to RFC 2616, "Hypertext Transfer Protocol -- HTTP/1.1", the
preferred method is to send a Location: header instead of a
Content-Type: header:

    Location: http://www.domain.com/newpage

Note that relative URLs in these headers can cause strange effects
because of "optimizations" that servers do.

    $url = "http://www.perl.com/CPAN/";
    print "Location: $url\n\n";
    exit;

To target a particular frame in a frameset, include the "Window-target:"
in the header.

    print <<EOF;
    Location: http://www.domain.com/newpage
    Window-target: <FrameName>

    EOF

To be correct to the spec, each of those virtual newlines should
really be physical "\015\012" sequences by the time your message is
received by the client browser.  Except for NPH scripts, though, that
local newline should get translated by your server into standard form,
so you shouldn't have a problem here, even if you are stuck on MacOS.
Everybody else probably won't even notice.

What's wrong with the quoted item?

This is covered in some detail in the fuller discussion below. Several 0.n drafts were previously discussed on c.l.perl.misc and a similar invitation was posted to comp.infosystems.www.authoring.cgi. Based on the discussions, and modified in respect of subsequent editing of the FAQ itself, this draft proposal is made.

Proposal

I'm a bit concerned that the result has turned out larger than I had intended. I tried to prune it down, but didn't seem to be able to do so without taking out bits that seemed to be significant.

This page has been inspected on the Lynx browser and it appears to me that the proposed items are acceptable for a plaintext FAQ in that form. It's being offered in HTML for comfortable evaluation: naturally the final result could be produced in an appropriate format (POD etc.) as desired.

Proposed material

Q: What is the correct form of response from a CGI script?

The Common Gateway Interface (CGI) specifies a software interface between a program ("CGI script") and a web server (HTTPD). It is not specific to Perl, and has its own FAQs and tutorials, and usenet group, comp.infosystems.www.authoring.cgi

The original CGI specification is at: http://hoohoo.ncsa.uiuc.edu/cgi/
Current best-practice RFC draft at: http://CGI-Spec.Golux.Com/

This Perl FAQ very selectively covers some CGI issues. However, Perl programmers are strongly advised to use the CGI.pm module, to take care of the details for them.

The similarity between CGI response headers (defined in the CGI specification) and HTTP response headers (defined in the HTTP specification, RFC2616) is intentional, but can sometimes be confusing.

The CGI specification defines two kinds of script: the "Parsed Header" script, and the "Non Parsed Header" (NPH) script. Check your server documentation to see what it supports.

"Parsed Header" scripts are simpler in various respects. The CGI specification allows any of the usual newline representations in the CGI response (it's the server's job to create an accurate HTTP response based on it). So "\n" written in text mode is technically correct, and recommended.

NPH scripts are more tricky: they must put out a complete and accurate set of HTTP transaction response headers; the HTTP specification calls for records to be terminated with carriage-return and line-feed, i.e ASCII \015\012 written in binary mode.

Using CGI.pm gives excellent platform independence, including EBCDIC systems. CGI.pm selects an appropriate newline representation ($CGI::CRLF) and sets binmode as appropriate.


Q: How do I redirect to another page?

Specify the complete URL of the destination (even if it is on the same server). This is one of the two different kinds of CGI "Location:" response which are defined in the CGI specification for a Parsed Headers script. The other kind (an absolute URLpath) is resolved internally to the server without any HTTP redirection. The CGI specifications do not allow relative URLs in either case.

Use of CGI.pm is strongly recommended, e.g as in this fragment.

      use CGI qw/:standard/;

      $url = 'http://www.perl.com/CPAN/';
      print redirect($url);

But if coded directly, it could be as follows (the final "\n" is shown separately, for clarity).

      $url = 'http://www.perl.com/CPAN/';
      print "Location: $url\n";   # CGI response header
      print "\n";                 # end of headers

Beyond the scope of this FAQ:


(By the way, I do have a separate page dealing with redirection in response to a POST transaction, but it's not part of the current proposal.)

The full half-hour argument

Please let me stress that this does not form part of the proposed FAQ text. It is here to clarify the considerations that went into drafting the suggested replacement. (Of course, if the Guardians-of-the-FAQ would like to use any of this material for the FAQ then by all means do so; I've tried to keep the actual proposal as terse as I could.)

CGI spec

Perlfaq9 currently cites the W3C CGI page. However, that links to a number of historical relics: I felt it was useful to point directly to Coar's page.

Some of the content which I have provided in the additional FAQ is, it's true, general information about the CGI that has nothing specifically to do with Perl. However, the Perl-specific answers seemed to me to be "adrift" without some introductory positioning. I've already discussed the alternative option of declaring these to be off-topic for Perl and excluding that area of coverage more radically.

Inappropriate place

It seemed inappropriate to slip-in casual remarks about the general format of a CGI response, i.e

To be correct to the spec, each of those virtual newlines should
really be physical "\015\012" sequences

into a specific answer about how to perform a redirection. If this issue is to be covered at all, it seems to call for a more generic FAQ topic header.

The distinction between a CGI response header and an HTTP response header can be a subtle one, and ignoring the difference is often harmless. However, there are significant contexts where a failure to appreciate the difference leads to real problems. The Location: header is one such, and there are others in practice (even if those might be outside of the scope of what these Perl CGI FAQs cover), so I do urge that this distinction should be pointed up in the FAQs.

Newlines as "\n" or "\015\012" or what?

This part of the FAQ is better than it used to be, but I'm still uneasy with it. It fuzzies the distinction between the CGI specification and the requirements of the HTTP RFC in a way that I don't really find helpful. If "\015\012" was the correct answer, what would be the point in giving an answer that's only correct on some platforms ("\n") and then qualifying it as potentially platform-specific? This would make the answer pointlessly confusing and complex.

There's a most instructive presentation about portable newline representations, in the perlport document included in the Perl distribution; it can be read using perldoc perlport.

However, the best-current-practice CGI draft allows any of the usual newline representations to be used on a "Parsed Header" CGI response - and as far as I know this does actually reflect practice on the available servers, so this distinction should be an irrelevance in that context. Nevertheless, CGI.pm contains code to deal with a wide range of platforms, and the best advice is to use that, rather than worrying about the details oneself.

In the NPH context, the CGI draft does not say anything explicit about this issue: it calls for a "complete HTTP response message". Since the HTTP specification calls for CR+LF as the correct network line-end, it may be worth including this point in the FAQ text (and I have done so, or it could be added to the list of things considered to be outside the scope of the FAQ). But as we see in CGI.pm and in the cited perlport discussion, \015\012 is also not quite the universal answer, see e.g EBCDIC coding.

I had a brief exchange of email with Ken Coar himself, who confirms my interpretation of the newline issues for Parsed Header and for NPH scripts respectively.

Quote marks etc.

A contributor to the usenet discussion considered that the original

      $url = "http://www.perl.com/CPAN/";

using doublequotes was poor Perl style. Accordingly I have replaced them with single quotes (apostrophes).

Another contributor complained about the frequency with which beginners are confused by seeing a double newline at the end of a CGI response header:

      print "Location: $url\n\n";

and requested that for didactic reasons the final "\n" should be split off, with appropriate comments, which I have now done, i.e:

      print "Location: $url\n";   # CGI response header
      print "\n";                 # end of headers

"relative URLs can cause strange effects"??

Not according to the specification, no! Truly relative URLs are not allowed by the specification in either kind of Location: response.

According to the CGI specification, there are two kinds of "Location:" response: a full URL, which must result in a redirection transaction (even if the reference is to the same server); and an absolute URL-path, which must directly return the specified resource on the same server, without an HTTP redirection.

The specification permits no optimization of the kind mooted by the existing FAQ. The two different kinds of Location: response were already distinct in the original NCSA CGI specification - it isn't something that has been recently adopted.

I do not know what was in the mind of the author of the remark, but my proposal would be to tell people what the CGI spec requires them to do, and not try to discuss possible consequences of doing something which the CGI spec does not codify and which brings no benefit.

Copyright release

This proposal is made available to the Perl FAQ compilers to be used in original or modified form as they see fit.


|Up| |RagBag|About the author|