httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeff Trawick <trawi...@bellsouth.net>
Subject Re: providing content-length
Date Mon, 30 Oct 2000 19:10:55 GMT
rbb@covalent.net writes:

> > > Why?  We only add it if we know that we have all the information.  We
> > > don't add it if we have to save ANY data off to the side.  This seems
> > > rather straight-forward to me, and it is what Roy has said in the past as
> > > well.
> > 
> > I'm a bit confused... maybe you can tell me which (if any) is the
> > proper interpretation of what you are saying.
> > 
> > . your comment above says (I think) "compute content length if the
> >   first brigade is the only brigade (i.e., if the last bucket is EOS)"
> > 
> > . your comment in a separate note says (I think) "if we can't send
> >   chunked then compute content length, buffering if needed"
> > 
> > My patch is closer to the second interpretation.
> 
> I'm saying both.  :-)  If we are allowed to send chunked-encoding then we
> only compute content length if we have all the information in the first
> pass.  If we aren't allowed to send chunked-encoding, then we have no
> choice but to buffer the data.

okey dokey...  Here is another patch, with simplifications to the
algorithm (wait until the end to calculate content-length) and the
implementation of more required checks to decide whether or not we
should go to the trouble...

Index: include/http_protocol.h
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/include/http_protocol.h,v
retrieving revision 1.35
diff -u -r1.35 http_protocol.h
--- include/http_protocol.h	2000/10/22 13:09:23	1.35
+++ include/http_protocol.h	2000/10/30 19:06:07
@@ -113,6 +113,8 @@
 AP_DECLARE(void) ap_send_http_header(request_rec *l);
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bucket_brigade
*b);
+AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *, 
+                                                              ap_bucket_brigade *);
 
 /* Send the response to special method requests */
 
@@ -533,6 +535,7 @@
 
 apr_status_t ap_http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode);
 apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode);
+
 
   /* Hooks */
   /*
Index: main/http_core.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/main/http_core.c,v
retrieving revision 1.190
diff -u -r1.190 http_core.c
--- main/http_core.c	2000/10/26 12:03:07	1.190
+++ main/http_core.c	2000/10/30 19:06:17
@@ -3578,6 +3578,8 @@
     ap_register_input_filter("DECHUNK", ap_dechunk_filter, AP_FTYPE_TRANSCODE);
     ap_register_input_filter("CORE_IN", core_input_filter, AP_FTYPE_NETWORK);
     ap_register_output_filter("HTTP_HEADER", ap_http_header_filter, AP_FTYPE_HTTP_HEADER);
+    ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter, 
+                              AP_FTYPE_HTTP_HEADER);
     ap_register_output_filter("CORE", core_output_filter, AP_FTYPE_NETWORK);
     ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, 
                               AP_FTYPE_CONTENT);
Index: main/http_protocol.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/main/http_protocol.c,v
retrieving revision 1.209
diff -u -r1.209 http_protocol.c
--- main/http_protocol.c	2000/10/26 11:05:07	1.209
+++ main/http_protocol.c	2000/10/30 19:06:19
@@ -1417,6 +1417,7 @@
                ? &r->server->keep_alive_timeout
                : &r->server->timeout);
 
+    ap_add_output_filter("CONTENT_LENGTH", NULL, r, r->connection);
     ap_add_output_filter("HTTP_HEADER", NULL, r, r->connection);
 
     /* Get the request... */
@@ -2227,6 +2228,77 @@
 
 AP_DECLARE(void) ap_send_http_header(request_rec *r)
 {
+}
+
+struct content_length_ctx {
+    ap_bucket_brigade *saved;
+};
+
+AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
+                                                              ap_bucket_brigade *b)
+{
+    request_rec *r = f->r;
+    struct content_length_ctx *ctx;
+    apr_status_t rv;
+    ap_bucket *e;
+
+    ctx = f->ctx;
+    if (!ctx) { /* first time through */
+        /* We won't compute a content length if one of the following is true:
+         * . subrequest
+         * . HTTP/0.9
+         * . content length already computed
+         * . can be chunked
+         */
+        if (r->assbackwards ||
+            apr_table_get(r->headers_out, "Content-Length") ||
+            (r->proto_num < HTTP_VERSION(1,1) &&
+             ap_find_last_token(f->r->pool,
+                                apr_table_get(r->headers_out,
+                                              "Transfer-Encoding"),
+                                "chunked"))) {
+            ap_remove_output_filter(f);
+            return ap_pass_brigade(f->next, b);
+        }
+
+        f->ctx = ctx = apr_pcalloc(r->pool, sizeof(struct content_length_ctx));
+    }
+
+    if (AP_BUCKET_IS_EOS(AP_BRIGADE_LAST(b))) {
+        apr_ssize_t content_length = 0;
+
+        if (ctx->saved) {
+            AP_BRIGADE_CONCAT(ctx->saved, b);
+            b = ctx->saved;
+        }
+
+        AP_BRIGADE_FOREACH(e, b) {
+            if (!AP_BUCKET_IS_EOS(e)) {
+                if (e->length >= 0) {
+                    content_length += e->length;
+                }
+                else {
+                    const char *ignored;
+                    apr_ssize_t length;
+                    
+                    rv = ap_bucket_read(e, &ignored, &length, 1);
+                    if (rv != APR_SUCCESS) {
+                        return rv;
+                    }
+                    content_length += e->length;
+                }
+            }
+        }
+
+        ap_set_content_length(r, content_length);
+        return ap_pass_brigade(f->next, b);
+    }
+
+    /* save the brigade; we can't pass any data to the next
+     * filter until we have the entire content length
+     */
+    ap_save_brigade(f, &ctx->saved, &b);
+    return APR_SUCCESS;
 }
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bucket_brigade
*b)

-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Mime
View raw message