stas        2004/03/02 13:05:32

  Modified:    src/docs/2.0/user/coding coding.pod
  Log:
  - new: Generating HTTP Response Headers
  - update: Forcing HTTP Response Headers Out
  - new: registry section
  - new: registry: A Look Behind the Scenes
  - new: registry: Getting the $r Object
  
  Revision  Changes    Path
  1.30      +187 -8    modperl-docs/src/docs/2.0/user/coding/coding.pod
  
  Index: coding.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/coding/coding.pod,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -u -r1.29 -r1.30
  --- coding.pod        12 Jan 2004 08:42:52 -0000      1.29
  +++ coding.pod        2 Mar 2004 21:05:32 -0000       1.30
  @@ -203,17 +203,106 @@
   In the following sections we discuss the specifics of Apache behavior
   relevant to mod_perl developers.
   
  -=head2 Sending HTTP Response Headers
  +=head2 HTTP Response Headers
  +
  +=head3 Generating HTTP Response Headers
  +
  +The best approach for generating HTTP response headers is by using the
  +L<mod_perl API|docs::2.0::api::Apache::RequestRec>. Some common
  +headers have dedicated methods, others are set by manipulating the
  +C<L<headers_out|docs::2.0::api::Apache::RequestRec/C_headers_out_>>
  +table directly.
  +
  +For example to set the I<Content-type> header you should call
  
+C<L<$r-E<gt>content_type|docs::2.0::api::Apache::RequestRec/C_content_type_>>:
  +
  +  use Apache::RequestRec ();
  +  $r->content_type('text/html');
  +
  +To C<L<set|docs::2.0::api::APR::Table/C_set_>> a custom header
  +I<My-Header> you should call:
  +
  +  use Apache::RequestRec ();
  +  use APR::Table;
  +  $r->headers_out->set(My-Header => "SomeValue");
  +
  +If you are inside a registry script L<you can still
  +access|docs::2.0::user::coding::coding/Getting_the_C__r__Object> the
  +C<L<Apache::RequestRec|docs::2.0::api::Apache::RequestRec>> object.
  +
  +Howerever you can choose a slower method of generating headers by just
  +printing them out before printing any response. This will work only if
  +C<L<PerlOptions
  ++ParseHeaders|docs::2.0::user::config::config/C_ParseHeaders_>> is
  +in effect. For example:
  +
  +   print "Content-type: text/html\n";
  +   print "My-Header: SomeValue\n";
  +   print "\n";
  +
  +This method is slower since Apache needs to parse the text to identify
  +certain headers it needs to know about. It also has several
  +limitations which we will now discuss.
  +
  +When using this approach you must make sure that the C<STDOUT>
  +filehandle is not set to flush the data after each print (which is set
  +by the value of a special perl variable C<$|>). Here we assume that
  +STDOUT is the currently C<select()>ed filehandle and C<$|> affects it.
  +
  +For example this code won't work:
  +
  +   local $| = 1;
  +   print "Content-type: text/html\n";
  +   print "My-Header: SomeValue\n";
  +   print "\n";
  +
  +Having a true C<$|> causes the first print() call to flush its data
  +immediately, which is sent to the internal HTTP header parser, which
  +will fail since it won't see the terminating C<"\n\n">. One solution
  +is to make sure that STDOUT won't flush immediately, like so:
  +
  +   local $| = 0;
  +   print "Content-type: text/html\n";
  +   print "My-Header: SomeValue\n";
  +   print "\n";
  +
  +Notice that we C<local()>ize that change, so it L<won't affect any
  +other
  
+code|docs::general::perl_reference::perl_reference/The_Scope_of_the_Special_Perl_Variables>.
  +
  +If you send headers line by line and their total length is bigger than
  +8k, you will have the header parser problem again, since mod_perl will
  +flush data when the 8k buffer gets full. In which case the solution is
  +not to print the headers one by one, but to buffer them all in a
  +variable and then print the whole set at once.
  +
  +Notice that you don't have any of these problems with mod_cgi, because
  +it ignores any of the flush attempts by Perl. mod_cgi simply opens a
  +pipe to the external process and reads any output sent from that
  +process at once.
  +
  +If you use C<$r> to set headers as explained at the beginning of this
  +section, you won't encounter any of these problems.
  +
  +Finally, If you don't want Apache to send its own headers and you want
  +to send your own set of headers (non-parsed headers handlers) use
  +explain the
  +C<L<$r-E<gt>assbackwards|docs::2.0::api::Apache::RequestRec/C_assbackwards_>>
  +method. Notice that registry handlers will do that for you if the
  +script's name start with the C<nph-> prefix.
  +
  +
  +=head3 Forcing HTTP Response Headers Out
   
   Apache 2.0 doesn't provide a method to force HTTP response headers
   sending (what used to be done by C<send_http_header()> in Apache
   1.3). HTTP response headers are sent as soon as the first bits of the
   response body are seen by the special core output filter that
  -generates these headers. When the response handler send the first
  +generates these headers. When the response handler sends the first
   chunks of body it may be cached by the mod_perl internal buffer or
   even by some of the output filters. The response handler needs to
  -flush in order to tell all the components participating in the sending
  -of the response to pass the data out.
  +flush the output in order to tell all the components participating in
  +the sending of the response to pass the data out.
   
   For example if the handler needs to perform a relatively long-running
   operation (e.g. a slow db lookup) and the client may timeout if it
  @@ -230,11 +319,14 @@
     }
   
   If this doesn't work, check whether you have configured any
  -third-party output filters for the resource in question. Improperly
  -written filter may ignore the orders to flush the data.
  +third-party output filters for the resource in question. L<Improperly
  +written
  +filter|docs::2.0::user::handlers::filters/Writing_Well_Behaving_Filters>
  +may ignore the command to flush the data.
  +
  +
  +
   
  -META: add a link to the notes on how to write well-behaved filters
  -at handlers/filters
   
   =head2 Sending HTTP Response Body
   
  @@ -246,11 +338,17 @@
   the issues is that the HTTP response filters are not setup before the
   response phase.
   
  +
  +
  +
   =head1 Perl Specifics in the mod_perl Environment
   
   In the following sections we discuss the specifics of Perl behavior
   under mod_perl.
   
  +
  +
  +
   =head2 Request-localized Globals
   
   mod_perl 2.0 provides two types of C<SetHandler> handlers:
  @@ -295,6 +393,87 @@
   
   You can still call C<CORE::exit> to kill the interpreter, again if you
   know what you are doing.
  +
  +
  +
  +
  +=head1 C<ModPerl::Registry> Handlers Family
  +
  +=head2 A Look Behind the Scenes
  +
  +If you have a CGI script F<test.pl>:
  +
  +  #!/usr/bin/perl
  +  print "Content-type: text/plain\n\n";
  +  print "Hello";
  +
  +a typical registry family handler turns it into something like:
  +
  +  package foo_bar_baz;
  +  sub handler {
  +      local $0 = "/full/path/to/test.pl";
  +  #line 1 test.pl
  +      #!/usr/bin/perl
  +      print "Content-type: text/plain\n\n";
  +      print "Hello";
  +  }
  +
  +Turning it into an almost full-fledged mod_perl handler. The only
  +difference is that it handles the return status for you. (META: more
  +details on return status needed.)
  +
  +It then executes it as:
  +
  +  foo_bar_baz::handler($r);
  +
  +passing the C<L<$r|docs::2.0::api::Apache::RequestRec>> object as the
  +only argument to the C<handler()> function.
  +
  +Depending on the used registry handler the package is made of the file
  +path, the uri or anything else. Check the handler's documentation to
  +learn which method is used.
  +
  +
  +
  +=head2 Getting the C<$r> Object
  +
  +As explained in L<A Look Behind the Scenes|/A_Look_Behind_the_Scenes>
  +the C<$r> object is always passed to the registry script's special
  +function C<handler> as the first and the only argument, so you can get
  +this object by accessing C<@_>, since:
  +
  +  my $r = shift;
  +  print "Content-type: text/plain\n\n";
  +  print "Hello";
  +
  +is turned into:
  +
  +  sub handler {
  +      my $r = shift;
  +      print "Content-type: text/plain\n\n";
  +      print "Hello";
  +  }
  +
  +behind the scenes. Now you can use C<$r> to call various mod_perl
  +methods, e.g. rewriting the script as:
  +
  +  my $r = shift;
  +  $r->content_type('text/plain');
  +  $r->print();
  +
  +If you are deep inside some code and can't get to the entry point to
  +reach for C<$r>, you can use
  +C<L<Apache-E<gt>request|docs::2.0::api::Apache::RequestUtil/C_request_>>.
  +
  +
  +
  +
  +
  +
  +
  +
  +
  +
   
   
   =head1 Threads Coding Issues Under mod_perl
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to