From d6cf33982408492af23d648ca69ac1f98857e915 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Tue, 7 Nov 2000 00:58:49 +0000 Subject: [PATCH] Always compute the content-length regardless of whether it is sent to the 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 | 92 ++++++++++++-------------------- modules/loggers/mod_log_config.c | 8 +-- 2 files changed, 37 insertions(+), 63 deletions(-) diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index b928983e17..f0b24ecc36 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -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; } diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index dbadb25d75..eea5b12019 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -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); } } -- 2.40.0