From: Yann Ylavic Date: Thu, 7 May 2015 14:05:25 +0000 (+0000) Subject: http: Don't remove the Content-Length of zero from a HEAD response if X-Git-Tag: 2.5.0-alpha~3170 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=725bf57c4b1e1a80ba140182ee042f4a08156afc;p=thirdparty%2Fapache%2Fhttpd.git http: Don't remove the Content-Length of zero from a HEAD response if it comes from an origin server, module or script. Instead of removing the C-L in ap_http_header_filter() after it has been set by ap_content_length_filter(), just don't set it in the latter. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1678215 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 351deff5553..b6b5fea2e5c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) http: Don't remove the Content-Length of zero from a HEAD response if + it comes from an origin server, module or script. [Yann Ylavic] + *) core/util_script: make REDIRECT_URL a full URL. PR 57785. [Nick Kew] *) mod_ssl: Check for the Entropy Gathering Daemon (EGD) availability at diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 4bc7c821130..7ebb619f556 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -1127,7 +1127,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, { request_rec *r = f->r; conn_rec *c = r->connection; - const char *clheader; const char *protocol = NULL; apr_bucket *e; apr_bucket_brigade *b2; @@ -1274,30 +1273,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, apr_table_addn(r->headers_out, "Expires", date); } - /* This is a hack, but I can't find anyway around it. The idea is that - * we don't want to send out 0 Content-Lengths if it is a head request. - * This happens when modules try to outsmart the server, and return - * if they see a HEAD request. Apache 1.3 handlers were supposed to - * just return in that situation, and the core handled the HEAD. In - * 2.0, if a handler returns, then the core sends an EOS bucket down - * the filter stack, and the content-length filter computes a C-L of - * zero and that gets put in the headers, and we end up sending a - * zero C-L to the client. We can't just remove the C-L filter, - * because well behaved 2.0 handlers will send their data down the stack, - * and we will compute a real C-L for the head request. RBB - * - * Allow modification of this behavior through the - * HttpContentLengthHeadZero directive. - * - * The default (unset) behavior is to squelch the C-L in this case. - */ - if (r->header_only - && (clheader = apr_table_get(r->headers_out, "Content-Length")) - && !strcmp(clheader, "0") - && conf->http_cl_head_zero != AP_HTTP_CL_HEAD_ZERO_ENABLE) { - apr_table_unset(r->headers_out, "Content-Length"); - } - b2 = apr_brigade_create(r->pool, c->bucket_alloc); basic_http_header(r, b2, protocol); diff --git a/server/protocol.c b/server/protocol.c index 9c05108ada6..5759f69afac 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -1533,10 +1533,35 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter( * We can only set a C-L in the response header if we haven't already * sent any buckets on to the next output filter for this request. */ - if (ctx->data_sent == 0 && eos && + if (ctx->data_sent == 0 && eos) { + core_server_config *conf = + ap_get_core_module_config(r->server->module_config); + + /* This is a hack, but I can't find anyway around it. The idea is that + * we don't want to send out 0 Content-Lengths if it is a HEAD request. + * [Unless the corresponding body (for a GET) would really be empty!] + * This happens when modules try to outsmart the server, and return + * if they see a HEAD request. Apache 1.3 handlers were supposed to + * just return in that situation, and the core handled the HEAD. From + * 2.0, if a handler returns, then the core sends an EOS bucket down + * the filter stack, and this content-length filter computes a length + * of zero and we would end up sending a zero C-L to the client. + * We can't just remove the this C-L filter, because well behaved 2.0+ + * handlers will send their data down the stack, and we will compute + * a real C-L for the head request. RBB + * + * Allow modification of this behavior through the + * HttpContentLengthHeadZero directive. + * + * The default (unset) behavior is to squelch the C-L in this case. + */ + /* don't whack the C-L if it has already been set for a HEAD * by something like proxy. the brigade only has an EOS bucket - * in this case, making r->bytes_sent zero. + * in this case, making r->bytes_sent zero, and either there is + * an existing C-L we want to preserve, or r->sent_bodyct is not + * zero (the empty body is being sent) thus we don't want to add + * a C-L of zero (the backend did not provide it, neither do we). * * if r->bytes_sent > 0 we have a (temporary) body whose length may * have been changed by a filter. the C-L header might not have been @@ -1544,9 +1569,13 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter( * such filters update or remove the C-L header, and just use it * if present. */ - !(r->header_only && r->bytes_sent == 0 && - apr_table_get(r->headers_out, "Content-Length"))) { - ap_set_content_length(r, r->bytes_sent); + if (!(r->header_only + && !r->bytes_sent + && (r->sent_bodyct + || conf->http_cl_head_zero != AP_HTTP_CL_HEAD_ZERO_ENABLE + || apr_table_get(r->headers_out, "Content-Length")))) { + ap_set_content_length(r, r->bytes_sent); + } } ctx->data_sent = 1;