You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Bill Stoddard <bi...@wstoddard.com> on 2001/06/25 18:13:51 UTC

Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()

I have a module that calls ap_rwrite() followed by ap_rflush().  Content length is not
provided so Apache 2.0 chunks the response.

Here is what happens...
I call ap_rwrite() to write a x75 len byte stream.  All the correct headers are built, and
the content is buffered by the OLD_WRITE filter. Then I call ap_rflush() which causes the
headers to be sent on the wire along with the first chunk (x75 length). My handler is done
at this point and returns control to Apache.  The next thing Apache sends on the wire is
the 0 byte chunk header to indicate that the response is done.

The problem: IE chokes when it receives just the 0 byte chunk header in a packet.

Thoughts?

Bill


Re: [PATCH] Re: We have a bug in Apache 2.0 chunking...

Posted by rb...@covalent.net.
+1

Ryan

On Tue, 26 Jun 2001, Bill Stoddard wrote:

> This patch seems to fix the problem. Comments before I commit it?
>
> Bill
>
> Index: http_core.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v
> retrieving revision 1.279
> diff -u -r1.279 http_core.c
> --- http_core.c 2001/06/07 01:14:24 1.279
> +++ http_core.c 2001/06/26 13:50:20
> @@ -144,6 +144,7 @@
>      for (more = NULL; b; b = more, more = NULL) {
>   apr_off_t bytes = 0;
>          apr_bucket *eos = NULL;
> +        apr_bucket *flush = NULL;
>          char chunk_hdr[20]; /* enough space for the snprintf below */
>
>   APR_BRIGADE_FOREACH(e, b) {
> @@ -152,6 +153,9 @@
>    eos = e;
>    break;
>       }
> +            if (APR_BUCKET_IS_FLUSH(e)) {
> +                flush = e;
> +            }
>       else if (e->length == -1) {
>                  /* unknown amount of data (e.g. a pipe) */
>    const char *data;
> @@ -206,12 +210,15 @@
>              APR_BRIGADE_INSERT_HEAD(b, e);
>
>              /*
> -             * Insert the end-of-chunk CRLF before the EOS bucket, or
> -             * appended to the brigade
> +             * Insert the end-of-chunk CRLF before an EOS or
> +             * FLUSH bucket, or appended to the brigade
>               */
>              e = apr_bucket_immortal_create(ASCII_CRLF, 2);
>              if (eos != NULL) {
>                  APR_BUCKET_INSERT_BEFORE(eos, e);
> +            }
> +            else if (flush != NULL) {
> +                APR_BUCKET_INSERT_BEFORE(flush, e);
>              }
>              else {
>                  APR_BRIGADE_INSERT_TAIL(b, e);
>
>
> > > I've looked into this a bit more and it appears we have a chunking bug in Apache 2.0.
> > > Specifically, Apache 2.0 is not terminating the first chunk with a CRLF as it should.
> > >
> >
>
>
>


_____________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
Covalent Technologies			rbb@covalent.net
-----------------------------------------------------------------------------


Re: [PATCH] Re: We have a bug in Apache 2.0 chunking...

Posted by Cliff Woolley <cl...@yahoo.com>.
On Tue, 26 Jun 2001, Bill Stoddard wrote:

> This patch seems to fix the problem. Comments before I commit it?

Makes sense to me... +1

--Cliff

--------------------------------------------------------------
   Cliff Woolley
   cliffwoolley@yahoo.com
   Charlottesville, VA



[PATCH] Re: We have a bug in Apache 2.0 chunking...

Posted by Bill Stoddard <bi...@wstoddard.com>.
This patch seems to fix the problem. Comments before I commit it?

Bill

Index: http_core.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v
retrieving revision 1.279
diff -u -r1.279 http_core.c
--- http_core.c 2001/06/07 01:14:24 1.279
+++ http_core.c 2001/06/26 13:50:20
@@ -144,6 +144,7 @@
     for (more = NULL; b; b = more, more = NULL) {
  apr_off_t bytes = 0;
         apr_bucket *eos = NULL;
+        apr_bucket *flush = NULL;
         char chunk_hdr[20]; /* enough space for the snprintf below */
 
  APR_BRIGADE_FOREACH(e, b) {
@@ -152,6 +153,9 @@
   eos = e;
   break;
      }
+            if (APR_BUCKET_IS_FLUSH(e)) {
+                flush = e;
+            }
      else if (e->length == -1) {
                 /* unknown amount of data (e.g. a pipe) */
   const char *data;
@@ -206,12 +210,15 @@
             APR_BRIGADE_INSERT_HEAD(b, e);
 
             /*
-             * Insert the end-of-chunk CRLF before the EOS bucket, or
-             * appended to the brigade
+             * Insert the end-of-chunk CRLF before an EOS or
+             * FLUSH bucket, or appended to the brigade
              */
             e = apr_bucket_immortal_create(ASCII_CRLF, 2);
             if (eos != NULL) {
                 APR_BUCKET_INSERT_BEFORE(eos, e);
+            }
+            else if (flush != NULL) {
+                APR_BUCKET_INSERT_BEFORE(flush, e);
             }
             else {
                 APR_BRIGADE_INSERT_TAIL(b, e);


> > I've looked into this a bit more and it appears we have a chunking bug in Apache 2.0.
> > Specifically, Apache 2.0 is not terminating the first chunk with a CRLF as it should.
> >
> 



Re: We have a bug in Apache 2.0 chunking...

Posted by Bill Stoddard <bi...@wstoddard.com>.
> I've looked into this a bit more and it appears we have a chunking bug in Apache 2.0.
> Specifically, Apache 2.0 is not terminating the first chunk with a CRLF as it should.
>

The problem is in this section of code I believe...

  /*
   * Insert the chunk header, specifying the number of bytes in
   * the chunk.
   */
   hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
                                   "%qx" CRLF, (apr_uint64_t)bytes);
   ap_xlate_proto_to_ascii(chunk_hdr, hdr_len);
   e = apr_bucket_transient_create(chunk_hdr, hdr_len);
   APR_BRIGADE_INSERT_HEAD(b, e);

   /*
    * Insert the end-of-chunk CRLF before the EOS bucket, or
    * appended to the brigade
    */
    e = apr_bucket_immortal_create(ASCII_CRLF, 2);
    if (eos != NULL) {
         APR_BUCKET_INSERT_BEFORE(eos, e);
    }
    else {
          APR_BRIGADE_INSERT_TAIL(b, e);
    }

We are adding the end-of-chunk bucket -after- the flush bucket when we should be adding it
before the flush bucket.  (as we do for the eos bucket).

Bill


Re: We have a bug in Apache 2.0 chunking...

Posted by Bill Stoddard <bi...@wstoddard.com>.
I've looked into this a bit more and it appears we have a chunking bug in Apache 2.0.
Specifically, Apache 2.0 is not terminating the first chunk with a CRLF as it should.

I send the server this request:
GET /test.jsp  HTTP/1.1
HOST: 127.0.0.1

and here is what I get back...

********** Apache 2.0  (IE chokes on this response) **********
HTTP/1.1 200 OK\r\n
Date: Tue, 26 Jun 2001 12:15:55 GMT\r\n
Server: Apache/2.0.19-dev (Win32) DAV/2\r\n
Set-Cookie: JSESSIONID=0000U2XZ0EANV22F11VVW2OEL5Y:-1;Path=/\r\n
Cache-Control: no-cache="set-cookie,set-cookie2"\r\n
Expires: Thu, 01 Dec 1994 16:00:00 GMT\r\n
Transfer-Encoding: chunked\r\n
Content-Type: text/html;charset=Cp1252\r\n
Content-Language: en\r\n
\r\n
79\r\n
<html> \r\n
\r\n
<head> \r\n
   <title>Really Simple</title> \r\n
</head> \r\n
<body> \r\n
<h1>Hello from Rhino\r\n
</h1>\r\n
</body> \r\n
</html>\r\n
0\r\n
\r\n

********** 1.3.20 (IE displays this properly) *********
HTTP/1.1 200 OK\r\n
Date: Tue, 26 Jun 2001 12:12:10 GMT\r\n
Server: Apache/1.3.20 (Win32)\r\n
Set-Cookie: JSESSIONID=0000KX2HYWEKBAP42NTADCLWURQ:-1;Path=/\r\n
Cache-Control: no-cache="set-cookie,set-cookie2"\r\n
Expires: Thu, 01 Dec 1994 16:00:00 GMT\r\n
Transfer-Encoding: chunked\r\n
Content-Type: text/html;charset=Cp1252\r\n
Content-Language: en\r\n
\r\n
79 \r\n
<html> \r\n
\r\n
<head> \r\n
   <title>Really Simple</title> \r\n
</head> \r\n
<body> \r\n
<h1>Hello from Rhino\r\n
</h1>\r\n
</body> \r\n
</html>\r\n
\r\n
0\r\n
\r\n

Bill

----- Original Message -----
From: "Bill Stoddard" <bi...@wstoddard.com>
To: <ne...@apache.org>
Sent: Monday, June 25, 2001 12:13 PM
Subject: Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()


> I have a module that calls ap_rwrite() followed by ap_rflush().  Content length is not
> provided so Apache 2.0 chunks the response.
>
> Here is what happens...
> I call ap_rwrite() to write a x75 len byte stream.  All the correct headers are built,
and
> the content is buffered by the OLD_WRITE filter. Then I call ap_rflush() which causes
the
> headers to be sent on the wire along with the first chunk (x75 length). My handler is
done
> at this point and returns control to Apache.  The next thing Apache sends on the wire is
> the 0 byte chunk header to indicate that the response is done.
>
> The problem: IE chokes when it receives just the 0 byte chunk header in a packet.
>
> Thoughts?
>
> Bill
>


Re: Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()

Posted by Chuck Murcko <ch...@topsail.org>.
On Tuesday, July 17, 2001, at 08:40 AM, Bill Stoddard wrote:

> Yes, here is the patch I committed to fix this problem...
>

Fixed it in the output filter. There's also a problem with the input 
filter, which is also the cause of the problems with 
http://www.apple.com/macosx/ in the proxy. The akamai servers which 
serve the images are apache-1.3.9/macosx, and they're sending us chunked 
data, which we're stalling on.

Chuck Murcko
Topsail Group
http://www.topsail.org/

Re: Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()

Posted by Bill Stoddard <bi...@wstoddard.com>.
Yes, here is the patch I committed to fix this problem...

Bill

Fix problem handling FLUSH bucket in the chunked encoding filter.
  Module was calling ap_rwrite() followed by ap_rflush() but the
  served content was not being displayed in the browser. Inspection
  of the output stream revealed that the first data chunk was
  missing the trailing CRLF required by the RFC

  Revision  Changes    Path
  1.230     +6 -0      httpd-2.0/CHANGES

  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.229
  retrieving revision 1.230
  diff -u -r1.229 -r1.230
  --- CHANGES 2001/06/20 01:46:28 1.229
  +++ CHANGES 2001/06/26 17:40:54 1.230
  @@ -1,5 +1,11 @@
   Changes with Apache 2.0.19-dev

  +  *) Fix problem handling FLUSH bucket in the chunked encoding filter.
  +     Module was calling ap_rwrite() followed by ap_rflush() but the
  +     served content was not being displayed in the browser. Inspection
  +     of the output stream revealed that the first data chunk was
  +     missing the trailing CRLF required by the RFC.
  +
     *) apxs no longer generates ap_send_http_header() in the example handler

     *) Fix an ab problem which could cause a divide-by-zero exception



  1.280     +9 -2      httpd-2.0/modules/http/http_core.c

  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v
  retrieving revision 1.279
  retrieving revision 1.280
  diff -u -r1.279 -r1.280
  --- http_core.c 2001/06/07 01:14:24 1.279
  +++ http_core.c 2001/06/26 17:40:58 1.280
  @@ -144,6 +144,7 @@
       for (more = NULL; b; b = more, more = NULL) {
   apr_off_t bytes = 0;
           apr_bucket *eos = NULL;
  +        apr_bucket *flush = NULL;
           char chunk_hdr[20]; /* enough space for the snprintf below */

   APR_BRIGADE_FOREACH(e, b) {
  @@ -152,6 +153,9 @@
   eos = e;
   break;
       }
  +            if (APR_BUCKET_IS_FLUSH(e)) {
  +                flush = e;
  +            }
       else if (e->length == -1) {
                   /* unknown amount of data (e.g. a pipe) */
   const char *data;
  @@ -206,12 +210,15 @@
               APR_BRIGADE_INSERT_HEAD(b, e);

               /*
  -             * Insert the end-of-chunk CRLF before the EOS bucket, or
  -             * appended to the brigade
  +             * Insert the end-of-chunk CRLF before an EOS or
  +             * FLUSH bucket, or appended to the brigade
                */
               e = apr_bucket_immortal_create(ASCII_CRLF, 2);
               if (eos != NULL) {
                   APR_BUCKET_INSERT_BEFORE(eos, e);
  +            }
  +            else if (flush != NULL) {
  +                APR_BUCKET_INSERT_BEFORE(flush, e);
               }
               else {
                   APR_BRIGADE_INSERT_TAIL(b, e);



----- Original Message -----
From: "Ian Holsman" <ia...@cnet.com>
To: <ne...@apache.org>
Sent: Monday, July 16, 2001 6:16 PM
Subject: Re: Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()


> On 25 Jun 2001 12:13:51 -0400, Bill Stoddard wrote:
> > I have a module that calls ap_rwrite() followed by ap_rflush().  Content length is not
> > provided so Apache 2.0 chunks the response.
> >
> > Here is what happens...
> > I call ap_rwrite() to write a x75 len byte stream.  All the correct headers are built,
and
> > the content is buffered by the OLD_WRITE filter. Then I call ap_rflush() which causes
the
> > headers to be sent on the wire along with the first chunk (x75 length). My handler is
done
> > at this point and returns control to Apache.  The next thing Apache sends on the wire
is
> > the 0 byte chunk header to indicate that the response is done.
> >
> > The problem: IE chokes when it receives just the 0 byte chunk header in a packet.
> >
> > Thoughts?
> >
> > Bill
>
>
> hi Bill,
> I was wondering if you got anywhere with this
> I'm seeing this with mod_proxy at the moment.
>
> my inital thought was to put some logic in the chunking filter
> just not to send the 0 byte chunk out.. can you see anything barfing
> on this?
>
> what do you think?
>
> --
> Ian Holsman          IanH@cnet.com
> Performance Measurement & Analysis
> CNET Networks   -   (415) 364-8608
>


Re: Nasty chunking bug (in MSIE?) when using ap_rwrite()/ap_rflush()

Posted by Ian Holsman <ia...@cnet.com>.
On 25 Jun 2001 12:13:51 -0400, Bill Stoddard wrote:
> I have a module that calls ap_rwrite() followed by ap_rflush().  Content length is not
> provided so Apache 2.0 chunks the response.
> 
> Here is what happens...
> I call ap_rwrite() to write a x75 len byte stream.  All the correct headers are built, and
> the content is buffered by the OLD_WRITE filter. Then I call ap_rflush() which causes the
> headers to be sent on the wire along with the first chunk (x75 length). My handler is done
> at this point and returns control to Apache.  The next thing Apache sends on the wire is
> the 0 byte chunk header to indicate that the response is done.
> 
> The problem: IE chokes when it receives just the 0 byte chunk header in a packet.
> 
> Thoughts?
> 
> Bill


hi Bill, 
I was wondering if you got anywhere with this
I'm seeing this with mod_proxy at the moment.

my inital thought was to put some logic in the chunking filter
just not to send the 0 byte chunk out.. can you see anything barfing
on this?

what do you think?

--
Ian Holsman          IanH@cnet.com
Performance Measurement & Analysis
CNET Networks   -   (415) 364-8608