]> granicus.if.org Git - apache/commitdiff
Always compute the content-length regardless of whether it is sent to the
authorRyan Bloom <rbb@apache.org>
Tue, 7 Nov 2000 00:58:49 +0000 (00:58 +0000)
committerRyan Bloom <rbb@apache.org>
Tue, 7 Nov 2000 00:58:49 +0000 (00:58 +0000)
client or not.  The reason for this, is that it allows us to log the
bytes sent to the client correctly.  This also simplifies the
content-length filter a bit, by making it a single pass through the
brigade.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86852 13f79535-47bb-0310-9956-ffa450edef68

modules/http/http_protocol.c
modules/loggers/mod_log_config.c

index b928983e1754dffdd9972ec93b68a76208218346..f0b24ecc367a3ab41761be6c0042ad864e4b90c6 100644 (file)
@@ -98,12 +98,6 @@ AP_HOOK_STRUCT(
            AP_HOOK_LINK(default_port)
 )
 
-#define SET_BYTES_SENT(r) \
-  do { if (r->sent_bodyct) \
-          ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
-  } while (0)
-
-
 /* if this is the first error, then log an INFO message and shut down the
  * connection.
  */
@@ -137,7 +131,6 @@ static int checked_bputstrs(request_rec *r, ...)
         return EOF;
     }
 
-    SET_BYTES_SENT(r);
     return n;
 }
 
@@ -1558,8 +1551,6 @@ static void end_output_stream(request_rec *r)
 void ap_finalize_sub_req_protocol(request_rec *sub)
 {
     end_output_stream(sub); 
-
-    SET_BYTES_SENT(sub->main);
 }
 
 /*
@@ -2131,7 +2122,7 @@ int ap_send_http_options(request_rec *r)
 
     terminate_header(buff);
 
-    ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
+    r->bytes_sent = 0;
 
     bb = ap_brigade_create(r->pool);
     b = ap_bucket_create_pool(buff, strlen(buff), r->pool);
@@ -2240,8 +2231,12 @@ AP_DECLARE(void) ap_send_http_header(request_rec *r)
 
 struct content_length_ctx {
     ap_bucket_brigade *saved;
+    int hold_data;    /* Whether or not to buffer the data. */
 };
 
+/* This filter computes the content length, but it also computes the number
+ * of bytes sent to the client.  This means that this filter will always run
+through all of the buckets in all brigades */
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
                                                               ap_bucket_brigade *b)
 {
@@ -2249,9 +2244,12 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
     struct content_length_ctx *ctx;
     apr_status_t rv;
     ap_bucket *e;
+    int send_it = 0;
 
     ctx = f->ctx;
     if (!ctx) { /* first time through */
+        f->ctx = ctx = apr_pcalloc(r->pool, sizeof(struct content_length_ctx));
+
         /* We won't compute a content length if one of the following is true:
          * . subrequest
          * . HTTP/0.9
@@ -2271,68 +2269,49 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
             || 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);
+                                                "chunked")) {
+            ctx->hold_data = 0;
+        }
+        else {
+            ctx->hold_data = 1;
         }
-
-        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;
+    AP_BRIGADE_FOREACH(e, b) {
+        const char *ignored;
+        apr_ssize_t length;
 
-        if (ctx->saved) {
-            AP_BRIGADE_CONCAT(ctx->saved, b);
-            b = ctx->saved;
+        if (AP_BUCKET_IS_EOS(e) || AP_BUCKET_IS_FLUSH(e)) {
+            ctx->hold_data = 0;
+            send_it = 1;
         }
-
-        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, AP_BLOCK_READ);
-                    if (rv != APR_SUCCESS) {
-                        return rv;
-                    }
-                    content_length += e->length;
-                }
-            }
+        rv = ap_bucket_read(e, &ignored, &length, AP_BLOCK_READ);
+        if (rv != APR_SUCCESS) {
+            return rv;
         }
-
-        ap_set_content_length(r, content_length);
-        return ap_pass_brigade(f->next, b);
+        r->bytes_sent += length;
     }
 
-    /* check for flush bucket... if there is one, we have to scratch
-     * the idea of providing content length because the output should
-     * flow immediately (for streaming dynamic content)
+    /* save the brigade; we can't pass any data to the next
+     * filter until we have the entire content length
      */
+    if (ctx->hold_data && !send_it) {
+        ap_save_brigade(f, &ctx->saved, &b);
+        return APR_SUCCESS;
+    }
 
-    AP_BRIGADE_FOREACH(e, b) {
-        if (AP_BUCKET_IS_FLUSH(e)) {
-            AP_BRIGADE_CONCAT(ctx->saved, b);
-            ap_remove_output_filter(f);
-            return ap_pass_brigade(f->next, ctx->saved);
-        }
+    if (ctx->saved) {
+        AP_BRIGADE_CONCAT(ctx->saved, b);
+        b = ctx->saved;
     }
 
-    /* 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_set_content_length(r, r->bytes_sent);
+    return ap_pass_brigade(f->next, b);
 }
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bucket_brigade *b)
 {
     int i;
-    const long int zero = 0L;
     char *date = NULL;
     request_rec *r = f->r;
     char *buff, *buff_start;
@@ -2344,6 +2323,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bu
     AP_DEBUG_ASSERT(!r->main);
 
     if (r->assbackwards) {
+        r->bytes_sent = 0;
         r->sent_bodyct = 1;
         ap_remove_output_filter(f);
         return ap_pass_brigade(f->next, b);
@@ -2439,7 +2419,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bu
 
     terminate_header(buff);
 
-    ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
     r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
 
     b2 = ap_brigade_create(r->pool);
@@ -2843,7 +2822,6 @@ AP_DECLARE(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t of
         total_bytes_sent += o;
     }
 
-    SET_BYTES_SENT(r);
     *nbytes = total_bytes_sent;
     return rv;
 } 
index dbadb25d755355e80845379506bcea5ae8bcdee5..eea5b12019a21357000e3910afa1fabb98421ce0 100644 (file)
@@ -374,9 +374,7 @@ static const char *clf_log_bytes_sent(request_rec *r, char *a)
         return "-";
     }
     else {
-        long int bs;
-        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
-       return apr_psprintf(r->pool, "%ld", bs);
+       return apr_psprintf(r->pool, "%ld", r->bytes_sent);
     }
 }
 
@@ -386,9 +384,7 @@ static const char *log_bytes_sent(request_rec *r, char *a)
         return "0";
     }
     else {
-        long int bs;
-        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
-       return apr_psprintf(r->pool, "%ld", bs);
+       return apr_psprintf(r->pool, "%ld", r->bytes_sent);
     }
 }