Commit f084f931 authored by Yann Ylavic's avatar Yann Ylavic
Browse files

http: Enforce consistently no response body with both 204 and 304 statuses.

Provide AP_STATUS_IS_HEADER_ONLY() helper/macro to check for 204 or 304 and
use it where some special treatment is needed when no body is expected.

Some of those places handled 204 only.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1837056 13f79535-47bb-0310-9956-ffa450edef68
parent 524f037d
Loading
Loading
Loading
Loading
+3 −0
Changes for CHANGES: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.5.1

  *) http: Enforce consistently no response body with both 204 and 304
     statuses.  [Yann Ylavic]

  *) mod_proxy_http: forward 100-continue, and minimize race conditions when
     reusing backend connections. PR 60330. [Yann Ylavic, Jean-Frederic Clere]

+4 −0
Changes for include/httpd.h: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -570,6 +570,10 @@ AP_DECLARE(const char *) ap_get_server_built(void);
                                    ((x) == HTTP_INTERNAL_SERVER_ERROR) || \
                                    ((x) == HTTP_SERVICE_UNAVAILABLE) || \
                                    ((x) == HTTP_NOT_IMPLEMENTED))

/** does the status imply header only response (i.e. never w/ a body)? */
#define AP_STATUS_IS_HEADER_ONLY(x) ((x) == HTTP_NO_CONTENT || \
                                     (x) == HTTP_NOT_MODIFIED)
/** @} */

/**
+3 −2
Changes for modules/filters/mod_brotli.c: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -346,11 +346,12 @@ static apr_status_t compress_filter(ap_filter_t *f, apr_bucket_brigade *bb)
        const char *accepts;

        /* Only work on main request, not subrequests, that are not
         * a 204 response with no content, and are not tagged with the
         * responses with no content (204/304), and are not tagged with the
         * no-brotli env variable, and are not a partial response to
         * a Range request.
         */
        if (r->main || r->status == HTTP_NO_CONTENT
        if (r->main
            || AP_STATUS_IS_HEADER_ONLY(r->status)
            || apr_table_get(r->subprocess_env, "no-brotli")
            || apr_table_get(r->headers_out, "Content-Range")) {
            ap_remove_output_filter(f);
+7 −5
Changes for modules/filters/mod_deflate.c: 7 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -642,18 +642,19 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,

        /*
         * Only work on main request, not subrequests,
         * that are not a 204 response with no content
         * that are not responses with no content (204/304),
         * and are not tagged with the no-gzip env variable
         * and not a partial response to a Range request.
         */
        if ((r->main != NULL) || (r->status == HTTP_NO_CONTENT) ||
        if ((r->main != NULL) ||
            AP_STATUS_IS_HEADER_ONLY(r->status) ||
            apr_table_get(r->subprocess_env, "no-gzip") ||
            apr_table_get(r->headers_out, "Content-Range")
           ) {
            if (APLOG_R_IS_LEVEL(r, APLOG_TRACE1)) {
                const char *reason =
                    (r->main != NULL)                           ? "subrequest" :
                    (r->status == HTTP_NO_CONTENT)              ? "no content" :
                    AP_STATUS_IS_HEADER_ONLY(r->status)         ? "no content" :
                    apr_table_get(r->subprocess_env, "no-gzip") ? "no-gzip" :
                    "content-range";
                ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
@@ -1532,11 +1533,12 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,

        /*
         * Only work on main request, not subrequests,
         * that are not a 204 response with no content
         * that are not responses with no content (204/304),
         * and not a partial response to a Range request,
         * and only when Content-Encoding ends in gzip.
         */
        if (!ap_is_initial_req(r) || (r->status == HTTP_NO_CONTENT) ||
        if (!ap_is_initial_req(r) ||
            AP_STATUS_IS_HEADER_ONLY(r->status) ||
            (apr_table_get(r->headers_out, "Content-Range") != NULL) ||
            (check_gzip(r, r->headers_out, r->err_headers_out) == 0)
           ) {
+9 −6
Changes for modules/http/http_filters.c: 9 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -1251,7 +1251,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
    }
    else if (ctx->headers_sent) {
        /* Eat body if response must not have one. */
        if (r->header_only || r->status == HTTP_NO_CONTENT) {
        if (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) {
            apr_brigade_cleanup(b);
            return APR_SUCCESS;
        }
@@ -1356,12 +1356,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
    basic_http_header_check(r, &protocol);
    ap_set_keepalive(r);

    if (r->chunked) {
        apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
    if (AP_STATUS_IS_HEADER_ONLY(r->status)) {
        apr_table_unset(r->headers_out, "Transfer-Encoding");
        apr_table_unset(r->headers_out, "Content-Length");
        r->content_type = r->content_encoding = NULL;
        r->content_languages = NULL;
        r->clength = r->chunked = 0;
    }

    if (r->status == HTTP_NO_CONTENT) {
    else if (r->chunked) {
        apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
        apr_table_unset(r->headers_out, "Content-Length");
    }

@@ -1440,7 +1443,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
    }
    ctx->headers_sent = 1;

    if (r->header_only || r->status == HTTP_NO_CONTENT) {
    if (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) {
        apr_brigade_cleanup(b);
        goto out;
    }
Loading