stas        2004/08/04 11:30:54

  Modified:    t/apache content_length_header.t
               t/response/TestApache content_length_header.pm
  Log:
  1) improve the discussion based on input from Geoff
  2) restore the explicit HEAD test where we want to get C-L, but no body is
  sent (this time using $r->rflush to force an early headers sending)
  
  Revision  Changes    Path
  1.2       +58 -20    modperl-2.0/t/apache/content_length_header.t
  
  Index: content_length_header.t
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/apache/content_length_header.t,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -u -r1.1 -r1.2
  --- content_length_header.t   2 Aug 2004 18:51:25 -0000       1.1
  +++ content_length_header.t   4 Aug 2004 18:30:54 -0000       1.2
  @@ -1,29 +1,26 @@
   use strict;
   use warnings FATAL => 'all';
   
  -# testing nuances of the HEAD request (e.g. when C-L header makes it
  -# through)
  -#
  -# because apache proclaims itself governor of the C-L header via
  -# the C-L filter, the important thing to test here is not when
  -# a C-L header is allowed to pass, but rather whether GET and HEAD
  -# behave the same wrt C-L under varying circumstances.
  -# for more discussion on why it is important to get HEAD requests
  -# right, see these threads from the mod_perl list
  -#   http://marc.theaimsgroup.com/?l=apache-modperl&m=108647669726915&w=2
  -#   http://marc.theaimsgroup.com/?t=109122984600001&r=1&w=2
  -# as well as this bug report from mozilla, which shows how they
  -# are using HEAD requests in the wild
  -#   http://bugzilla.mozilla.org/show_bug.cgi?id=245447
  -
   use Apache::Test;
   use Apache::TestUtil;
   use Apache::TestRequest;
   
  -plan tests => 12 * 2, todo => [2,5];
  +plan tests => 12 * 2 + 3, todo => [2,5];
   
   my $location = "/TestApache__content_length_header";
   
  +# 1. because Apache proclaims itself governor of the C-L header via
  +# the C-L filter (ap_content_length_filter at
  +# httpd-2.0/server/protocol.c), test whether GET and HEAD behave the
  +# same wrt C-L under varying circumstances.  for more discussion on
  +# why it is important to get HEAD requests right, see these threads
  +# from the mod_perl list
  +#   http://marc.theaimsgroup.com/?l=apache-modperl&m=108647669726915&w=2
  +#   http://marc.theaimsgroup.com/?t=109122984600001&r=1&w=2
  +# as well as this bug report from mozilla, which shows how they
  +# are using HEAD requests in the wild
  +#   http://bugzilla.mozilla.org/show_bug.cgi?id=245447
  +
   foreach my $method qw(GET HEAD) {
   
       no strict qw(refs);
  @@ -34,7 +31,8 @@
           my $uri = $location;
           my $res = $method->($uri);
           ok t_cmp $res->code, 200, "$method $uri code";
  -        ok t_cmp $res->header('Content-Length'), undef, "$method $uri C-L header";
  +        ok t_cmp $res->header('Content-Length'), undef,
  +            "$method $uri C-L header";
           ok t_cmp $res->content, "", "$method $uri content";
       }
   
  @@ -44,7 +42,8 @@
           my $uri = "$location?set_content_length";
           my $res = $method->($uri);
           ok t_cmp $res->code, 200, "$method $uri code";
  -        ok t_cmp $res->header('Content-Length'), undef, "$method $uri C-L header";
  +        ok t_cmp $res->header('Content-Length'), undef,
  +            "$method $uri C-L header";
           ok t_cmp $res->content, "", "$method $uri content";
       }
   
  @@ -54,7 +53,8 @@
           my $uri = "$location?send_body";
           my $res = $method->($uri);
           ok t_cmp $res->code, 200, "$method $uri code";
  -        ok t_cmp $res->header('Content-Length'), undef, "$method $uri C-L header";
  +        ok t_cmp $res->header('Content-Length'), undef,
  +            "$method $uri C-L header";
   
           my $content = $method eq 'GET' ? 'This is a response string' : '';
           ok t_cmp $res->content, $content, "$method $uri content";
  @@ -66,9 +66,47 @@
           my $uri = "$location?send_body+set_content_length";
           my $res = $method->($uri);
           ok t_cmp $res->code, 200, "$method $uri code";
  -        ok t_cmp $res->header('Content-Length'), 25, "$method $uri C-L header";
  +        ok t_cmp $res->header('Content-Length'), 25,
  +            "$method $uri C-L header";
   
           my $content = $method eq 'GET' ? 'This is a response string' : '';
           ok t_cmp $res->content, $content, "$method $uri content";
       }
  +}
  +
  +# 2. even though the spec says that content handlers should send an
  +# identical response for GET and HEAD requests, some folks try to
  +# avoid the overhead of generating the response body, which Apache is
  +# going to discard anyway for HEAD requests. The following discussion
  +# assumes that we deal with a HEAD request.
  +#
  +# When Apache sees EOS and no headers and no response body were sent,
  +# ap_content_length_filter (httpd-2.0/server/protocol.c) sets C-L to
  +# 0. Later on ap_http_header_filter
  +# (httpd-2.0/modules/http/http_protocol.c) removes the C-L header for
  +# the HEAD requests
  +#
  +# the workaround is to force the sending of the response headers,
  +# before EOS was sent. The simplest solution is to use rflush():
  +#
  +# if ($r->header_only) { # HEAD
  +#     $body_len = calculate_body_len();
  +#     $r->set_content_length($body_len);
  +#     $r->rflush;
  +# }
  +# else {                 # GET
  +#     # generate and send the body
  +# }
  +#
  +# now if the handler sets the C-L header it'll be delivered to the
  +# client unmodified.
  +
  +{
  +    # if the response handler sends data (e.g. one char string), and
  +    # sets C-L header, the client gets the C-L header
  +    my $uri = "$location?head_no_body+set_content_length";
  +    my $res = HEAD $uri;
  +    ok t_cmp $res->code, 200, "HEAD $uri code";
  +    ok t_cmp $res->header('Content-Length'), 25, "HEAD $uri C-L header";
  +    ok t_cmp $res->content, '', "HEAD $uri content";
   }
  
  
  
  1.2       +8 -3      modperl-2.0/t/response/TestApache/content_length_header.pm
  
  Index: content_length_header.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/response/TestApache/content_length_header.pm,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -u -r1.1 -r1.2
  --- content_length_header.pm  2 Aug 2004 18:51:25 -0000       1.1
  +++ content_length_header.pm  4 Aug 2004 18:30:54 -0000       1.2
  @@ -1,6 +1,6 @@
   package TestApache::content_length_header;
   
  -# see the client for the comments
  +# see the client t/apache/content_length_header.t for the comments
   
   use strict;
   use warnings FATAL => 'all';
  @@ -25,9 +25,14 @@
       }
   
       if ($args =~ /send_body/) {
  -        # really could send just about anything, since Apache discards
  -        # the response body on HEAD requests
           $r->print($body);
  +    }
  +
  +    if ($args =~ /head_no_body/) {
  +        if ($r->header_only) {
  +            # see #2 in the discussion in the client
  +            $r->rflush;
  +        }
       }
   
       Apache::OK;
  
  
  

Reply via email to