You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2015/06/05 18:50:48 UTC

svn commit: r1683808 - in /httpd/httpd/branches/2.2.x: ./ include/ modules/cache/ modules/dav/fs/ modules/dav/main/ modules/generators/ modules/http/ modules/proxy/ modules/ssl/ server/

Author: wrowe
Date: Fri Jun  5 16:50:47 2015
New Revision: 1683808

URL: http://svn.apache.org/r1683808
Log:
core, modules: Avoid error response/document handling by the core if some
handler or input filter already did it while reading the request (causing
a double response body).

Submitted by: ylavic
Backports: r1482522 (partial, ap_map_http_request_error() things only!),
           r1529988, r1529991, r1643537, r1643543, r1657897, r1665625,
           r1665721, r1674056
Reviewed by: ylavic, wrowe, covener


Modified:
    httpd/httpd/branches/2.2.x/   (props changed)
    httpd/httpd/branches/2.2.x/CHANGES
    httpd/httpd/branches/2.2.x/STATUS
    httpd/httpd/branches/2.2.x/include/ap_mmn.h
    httpd/httpd/branches/2.2.x/include/http_protocol.h
    httpd/httpd/branches/2.2.x/modules/cache/mod_file_cache.c
    httpd/httpd/branches/2.2.x/modules/dav/fs/repos.c
    httpd/httpd/branches/2.2.x/modules/dav/main/mod_dav.c
    httpd/httpd/branches/2.2.x/modules/generators/mod_asis.c
    httpd/httpd/branches/2.2.x/modules/generators/mod_cgi.c
    httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
    httpd/httpd/branches/2.2.x/modules/http/http_filters.c
    httpd/httpd/branches/2.2.x/modules/http/http_request.c
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ajp.c
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_http.c
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_scgi.c
    httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c
    httpd/httpd/branches/2.2.x/server/core.c
    httpd/httpd/branches/2.2.x/server/error_bucket.c
    httpd/httpd/branches/2.2.x/server/util_xml.c

Propchange: httpd/httpd/branches/2.2.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jun  5 16:50:47 2015
@@ -1,2 +1,2 @@
 /httpd/httpd/branches/2.4.x:1555538,1555559,1648845,1649003,1681034,1682929,1682939
-/httpd/httpd/trunk:290940,395552,417988,451572,501364,583817,583830,611483,630858,639005,639010,647395,657354,657459,660461,660566,664330,678761,680082,681190,682369,683626,685112,686805,686809,687099,687754,693120,693392,693727-693728,696006,697093,706318,707163,708902,711421,713575,719357,720250,729316-729317,729586,732414,732504,732816,732832,733127,733134,733218-733219,734710,743589,755190,756671,756675,756678,756683,757741,761329,763394,764239,768535,769809,771587,771610,776325,777042,777091,778438-778439,778531,778942,780648,780655,780692,780697,780699,785457,785661,790587,803704,819480,823536,823563,834378,835046,891282,900022,932791,942209,952823,953311,955966,979120,981084,992625,1026743,1031551,1040304,1040373,1058192,1070096,1082189,1082196,1090645,1172732,1200040,1200372,1200374,1213380,1222335,1223048,1231446,1244211,1294306,1299738,1300171,1301111,1308862,1327036,1327080,1328133,1328325-1328326,1345319,1348656,1349905,1352912,1363183,1363186,1366344,1367778,1368131,136
 8396,1369568,1395225,1398066,1400700,1408402,1410681,1413732,1414094,1416889,1418752,1422234,1422253,1435178,1447426,1470940,1475878,1476604,1476621,1476642,1476644-1476645,1477530,1485409,1485668,1490994,1493330,1496429,1500323,1504276,1506714,1509872,1509875,1524192,1524770,1526168,1526189,1527291,1527295,1527925,1528718,1529559,1531505,1532816,1551685,1551714,1552227,1553204,1554276,1554281,1555240,1555555,1556428,1563420,1572092,1572198,1572543,1572611,1572630,1572655,1572663,1572668-1572671,1572896,1572911,1572967,1573224,1573229,1575400,1586745,1587594,1587639,1588851,1590509,1603156,1604353,1610207,1610311,1610491,1610501,1611165,1611169,1620932,1621453,1648840,1649001,1649043,1650310,1650320,1652929,1653997,1658765,1663647,1664205,1665215,1665218,1666363,1675533,1676654,1677462,1679182,1679470,1680895,1680900,1680942,1681037,1682923,1682937
+/httpd/httpd/trunk:290940,395552,417988,451572,501364,583817,583830,611483,630858,639005,639010,647395,657354,657459,660461,660566,664330,678761,680082,681190,682369,683626,685112,686805,686809,687099,687754,693120,693392,693727-693728,696006,697093,706318,707163,708902,711421,713575,719357,720250,729316-729317,729586,732414,732504,732816,732832,733127,733134,733218-733219,734710,743589,755190,756671,756675,756678,756683,757741,761329,763394,764239,768535,769809,771587,771610,776325,777042,777091,778438-778439,778531,778942,780648,780655,780692,780697,780699,785457,785661,790587,803704,819480,823536,823563,834378,835046,891282,900022,932791,942209,952823,953311,955966,979120,981084,992625,1026743,1031551,1040304,1040373,1058192,1070096,1082189,1082196,1090645,1172732,1200040,1200372,1200374,1213380,1222335,1223048,1231446,1244211,1294306,1299738,1300171,1301111,1308862,1327036,1327080,1328133,1328325-1328326,1345319,1348656,1349905,1352912,1363183,1363186,1366344,1367778,1368131,136
 8396,1369568,1395225,1398066,1400700,1408402,1410681,1413732,1414094,1416889,1418752,1422234,1422253,1435178,1447426,1470940,1475878,1476604,1476621,1476642,1476644-1476645,1477530,1485409,1485668,1490994,1493330,1496429,1500323,1504276,1506714,1509872,1509875,1524192,1524770,1526168,1526189,1527291,1527295,1527925,1528718,1529559,1529988,1529991,1531505,1532816,1551685,1551714,1552227,1553204,1554276,1554281,1555240,1555555,1556428,1563420,1572092,1572198,1572543,1572611,1572630,1572655,1572663,1572668-1572671,1572896,1572911,1572967,1573224,1573229,1575400,1586745,1587594,1587639,1588851,1590509,1603156,1604353,1610207,1610311,1610491,1610501,1611165,1611169,1620932,1621453,1643537,1643543,1648840,1649001,1649043,1650310,1650320,1652929,1653997,1657897,1658765,1663647,1664205,1665215,1665218,1665625,1665721,1666363,1674056,1675533,1676654,1677462,1679182,1679470,1680895,1680900,1680942,1681037,1682923,1682937

Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Fri Jun  5 16:50:47 2015
@@ -1,6 +1,13 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.2.30
 
+  *) http: Make ap_die() robust against any HTTP error code and not modify
+     response status (finally logged) when nothing is to be done. [Yann Ylavic]
+
+  *) core, modules: Avoid error response/document handling by the core if some
+     handler or input filter already did it while reading the request (causing
+     a double response body).  [Yann Ylavic]
+
   *) FreeBSD: Disable IPv4-mapped listening sockets by default for versions
      5+ instead of just for FreeBSD 5. PR 53824.  [Jeff Trawick,
      Olli Hauer <ohauer gmx de>]

Modified: httpd/httpd/branches/2.2.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/STATUS?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/STATUS (original)
+++ httpd/httpd/branches/2.2.x/STATUS Fri Jun  5 16:50:47 2015
@@ -109,23 +109,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
                   (modulo CHANGES)
      +1: ylavic, wrowe, covener
 
-  *) core, modules: Avoid error response/document handling by the core if some
-     handler or input filter already did it while reading the request (causing
-     a double response body).
-     trunk patch: http://svn.apache.org/r1482522 (partial, ap_map_http_request_error() things only!)
-                  http://svn.apache.org/r1529988
-                  http://svn.apache.org/r1529991
-                  http://svn.apache.org/r1643537
-                  http://svn.apache.org/r1643543
-                  http://svn.apache.org/r1657897
-                  http://svn.apache.org/r1665625
-                  http://svn.apache.org/r1665721
-                  http://svn.apache.org/r1674056
-     2.4.x patch: http://people.apache.org/~ylavic/httpd-2.4.x-ap_map_http_request_error-v2.patch
-     2.2.x patch: http://people.apache.org/~ylavic/httpd-2.2.x-ap_map_http_request_error-v2.patch
-     +1: ylavic, wrowe, covener
-     ylavic: Depends on httpd-2.2.x-ap_die.patch above.
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]

Modified: httpd/httpd/branches/2.2.x/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/ap_mmn.h?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/include/ap_mmn.h (original)
+++ httpd/httpd/branches/2.2.x/include/ap_mmn.h Fri Jun  5 16:50:47 2015
@@ -157,6 +157,7 @@
  * 20051115.37 (2.2.30) Add ap_get_server_name_for_url()
  * 20051115.38 (2.2.30) Add ap_proxy_set_scoreboard_lb() in mod_proxy.h
  * 20051115.39 (2.2.30) Add ap_proxy_connection_reusable()
+ * 20051115.40 (2.2.30) Add ap_map_http_request_error()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
@@ -164,7 +165,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20051115
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 39                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 40                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/branches/2.2.x/include/http_protocol.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/http_protocol.h?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/include/http_protocol.h (original)
+++ httpd/httpd/branches/2.2.x/include/http_protocol.h Fri Jun  5 16:50:47 2015
@@ -432,6 +432,23 @@ AP_DECLARE(int) ap_should_client_block(r
  */
 AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, apr_size_t bufsiz);
 
+/*
+ * Map specific APR codes returned by the filter stack to HTTP error
+ * codes, or the default status code provided. Use it as follows:
+ *
+ * return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+ *
+ * If the filter has already handled the error, AP_FILTER_ERROR will
+ * be returned, which is cleanly passed through.
+ *
+ * These mappings imply that the filter stack is reading from the
+ * downstream client, the proxy will map these codes differently.
+ * @param rv APR status code
+ * @param status Default HTTP code should the APR code not be recognised
+ * @return Mapped HTTP status code
+ */
+AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status);
+
 /**
  * In HTTP/1.1, any method can have a body.  However, most GET handlers
  * wouldn't know what to do with a request body if they received one.

Modified: httpd/httpd/branches/2.2.x/modules/cache/mod_file_cache.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/cache/mod_file_cache.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/cache/mod_file_cache.c (original)
+++ httpd/httpd/branches/2.2.x/modules/cache/mod_file_cache.c Fri Jun  5 16:50:47 2015
@@ -285,7 +285,7 @@ static int mmap_handler(request_rec *r,
     APR_BRIGADE_INSERT_TAIL(bb, b);
 
     if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
-        return HTTP_INTERNAL_SERVER_ERROR;
+        return AP_FILTER_ERROR;
 #endif
     return OK;
 }
@@ -304,7 +304,7 @@ static int sendfile_handler(request_rec
     APR_BRIGADE_INSERT_TAIL(bb, b);
 
     if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
-        return HTTP_INTERNAL_SERVER_ERROR;
+        return AP_FILTER_ERROR;
 #endif
     return OK;
 }

Modified: httpd/httpd/branches/2.2.x/modules/dav/fs/repos.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/dav/fs/repos.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/dav/fs/repos.c (original)
+++ httpd/httpd/branches/2.2.x/modules/dav/fs/repos.c Fri Jun  5 16:50:47 2015
@@ -999,7 +999,7 @@ static dav_error * dav_fs_deliver(const
     APR_BRIGADE_INSERT_TAIL(bb, bkt);
 
     if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) {
-        return dav_new_error(pool, HTTP_FORBIDDEN, 0,
+        return dav_new_error(pool, AP_FILTER_ERROR, 0,
                              "Could not write contents to filter.");
     }
 

Modified: httpd/httpd/branches/2.2.x/modules/dav/main/mod_dav.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/dav/main/mod_dav.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/dav/main/mod_dav.c (original)
+++ httpd/httpd/branches/2.2.x/modules/dav/main/mod_dav.c Fri Jun  5 16:50:47 2015
@@ -593,6 +593,11 @@ static int dav_handle_err(request_rec *r
     /* log the errors */
     dav_log_err(r, err, APLOG_ERR);
 
+    if (!ap_is_HTTP_VALID_RESPONSE(err->status)) {
+        /* we have responded already */
+        return AP_FILTER_ERROR;
+    }
+
     if (response == NULL) {
         dav_error *stackerr = err;
 
@@ -1004,8 +1009,17 @@ static int dav_method_put(request_rec *r
                                 APR_BLOCK_READ, DAV_READ_BLOCKSIZE);
 
             if (rc != APR_SUCCESS) {
-                err = dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
-                                    "Could not get next bucket brigade");
+                int http_err;
+                const char *msg;
+                if (APR_STATUS_IS_TIMEUP(rc)) {
+                    http_err = HTTP_REQUEST_TIME_OUT;
+                    msg = "Timeout reading the body";
+                }
+                else {
+                    http_err = ap_map_http_request_error(rc, HTTP_BAD_REQUEST);
+                    msg = "Error reading the body";
+                }
+                err = dav_new_error(r->pool, http_err, 0, msg);
                 break;
             }
 

Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_asis.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_asis.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/generators/mod_asis.c (original)
+++ httpd/httpd/branches/2.2.x/modules/generators/mod_asis.c Fri Jun  5 16:50:47 2015
@@ -118,7 +118,7 @@ static int asis_handler(request_rec *r)
         if (rv != APR_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                           "mod_asis: ap_pass_brigade failed for file %s", r->filename);
-            return HTTP_INTERNAL_SERVER_ERROR;
+            return AP_FILTER_ERROR;
         }
     }
     else {

Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_cgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_cgi.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/generators/mod_cgi.c (original)
+++ httpd/httpd/branches/2.2.x/modules/generators/mod_cgi.c Fri Jun  5 16:50:47 2015
@@ -839,7 +839,7 @@ static int cgi_handler(request_rec *r)
         if (rv != APR_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                           "Error reading request entity data");
-            return HTTP_INTERNAL_SERVER_ERROR;
+            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
         }
 
         for (bucket = APR_BRIGADE_FIRST(bb);

Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c (original)
+++ httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c Fri Jun  5 16:50:47 2015
@@ -1472,7 +1472,7 @@ static int cgid_handler(request_rec *r)
         if (rv != APR_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                           "Error reading request entity data");
-            return HTTP_INTERNAL_SERVER_ERROR;
+            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
         }
 
         for (bucket = APR_BRIGADE_FIRST(bb);

Modified: httpd/httpd/branches/2.2.x/modules/http/http_filters.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/http/http_filters.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/http/http_filters.c (original)
+++ httpd/httpd/branches/2.2.x/modules/http/http_filters.c Fri Jun  5 16:50:47 2015
@@ -418,7 +418,10 @@ apr_status_t ap_http_filter(ap_filter_t
                 e = apr_bucket_flush_create(f->c->bucket_alloc);
                 APR_BRIGADE_INSERT_TAIL(bb, e);
 
-                ap_pass_brigade(f->c->output_filters, bb);
+                rv = ap_pass_brigade(f->c->output_filters, bb);
+                if (rv != APR_SUCCESS) {
+                    return AP_FILTER_ERROR;
+                }
             }
         }
 
@@ -1398,6 +1401,39 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
     return ap_pass_brigade(f->next, b);
 }
 
+/*
+ * Map specific APR codes returned by the filter stack to HTTP error
+ * codes, or the default status code provided. Use it as follows:
+ *
+ * return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+ *
+ * If the filter has already handled the error, AP_FILTER_ERROR will
+ * be returned, which is cleanly passed through.
+ *
+ * These mappings imply that the filter stack is reading from the
+ * downstream client, the proxy will map these codes differently.
+ */
+AP_DECLARE(int) ap_map_http_request_error(apr_status_t rv, int status)
+{
+    switch (rv) {
+    case AP_FILTER_ERROR: {
+        return AP_FILTER_ERROR;
+    }
+    case APR_ENOSPC: {
+        return HTTP_REQUEST_ENTITY_TOO_LARGE;
+    }
+    case APR_ENOTIMPL: {
+        return HTTP_NOT_IMPLEMENTED;
+    }
+    case APR_ETIMEDOUT: {
+        return HTTP_REQUEST_TIME_OUT;
+    }
+    default: {
+        return status;
+    }
+    }
+}
+
 /* In HTTP/1.1, any method can have a body.  However, most GET handlers
  * wouldn't know what to do with a request body if they received one.
  * This helper routine tests for and reads any message body in the request,
@@ -1415,7 +1451,8 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
 AP_DECLARE(int) ap_discard_request_body(request_rec *r)
 {
     apr_bucket_brigade *bb;
-    int rv, seen_eos;
+    int seen_eos;
+    apr_status_t rv;
 
     /* Sometimes we'll get in a state where the input handling has
      * detected an error where we want to drop the connection, so if
@@ -1438,21 +1475,8 @@ AP_DECLARE(int) ap_discard_request_body(
                             APR_BLOCK_READ, HUGE_STRING_LEN);
 
         if (rv != APR_SUCCESS) {
-            /* FIXME: If we ever have a mapping from filters (apr_status_t)
-             * to HTTP error codes, this would be a good place for them.
-             *
-             * If we received the special case AP_FILTER_ERROR, it means
-             * that the filters have already handled this error.
-             * Otherwise, we should assume we have a bad request.
-             */
-            if (rv == AP_FILTER_ERROR) {
-                apr_brigade_destroy(bb);
-                return rv;
-            }
-            else {
-                apr_brigade_destroy(bb);
-                return HTTP_BAD_REQUEST;
-            }
+            apr_brigade_destroy(bb);
+            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
         }
 
         for (bucket = APR_BRIGADE_FIRST(bb);
@@ -1622,6 +1646,13 @@ AP_DECLARE(long) ap_get_client_block(req
     /* We lose the failure code here.  This is why ap_get_client_block should
      * not be used.
      */
+    if (rv == AP_FILTER_ERROR) {
+        /* AP_FILTER_ERROR means a filter has responded already,
+         * we are DONE.
+         */
+        apr_brigade_destroy(bb);
+        return -1;
+    }
     if (rv != APR_SUCCESS) {
         /* if we actually fail here, we want to just return and
          * stop trying to read data from the client.

Modified: httpd/httpd/branches/2.2.x/modules/http/http_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/http/http_request.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/http/http_request.c (original)
+++ httpd/httpd/branches/2.2.x/modules/http/http_request.c Fri Jun  5 16:50:47 2015
@@ -72,19 +72,22 @@ static void update_r_in_filters(ap_filte
     }
 }
 
-AP_DECLARE(void) ap_die(int type, request_rec *r)
+static void ap_die_r(int type, request_rec *r, int recursive_error)
 {
-    int error_index = ap_index_of_response(type);
-    char *custom_response = ap_response_code_string(r, error_index);
-    int recursive_error = 0;
+    char *custom_response;
     request_rec *r_1st_err = r;
 
-    if (type == AP_FILTER_ERROR) {
+    if (type == OK || type == DONE) {
+        ap_finalize_request_protocol(r);
+        return;
+    }
+
+    if (!ap_is_HTTP_VALID_RESPONSE(type)) {
         ap_filter_t *next;
 
         /*
          * Check if we still have the ap_http_header_filter in place. If
-         * this is the case we should not ignore AP_FILTER_ERROR here because
+         * this is the case we should not ignore the error here because
          * it means that we have not sent any response at all and never
          * will. This is bad. Sent an internal server error instead.
          */
@@ -98,8 +101,14 @@ AP_DECLARE(void) ap_die(int type, reques
          * next->frec == ap_http_header_filter
          */
         if (next) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "Custom error page caused AP_FILTER_ERROR");
+            if (type != AP_FILTER_ERROR) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "Invalid response status %i", type);
+            }
+            else {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                              "Response from AP_FILTER_ERROR");
+            }
             type = HTTP_INTERNAL_SERVER_ERROR;
         }
         else {
@@ -107,20 +116,13 @@ AP_DECLARE(void) ap_die(int type, reques
         }
     }
 
-    if (type == DONE) {
-        ap_finalize_request_protocol(r);
-        return;
-    }
-
     /*
      * The following takes care of Apache redirects to custom response URLs
      * Note that if we are already dealing with the response to some other
      * error condition, we just report on the original error, and give up on
      * any attempt to handle the other thing "intelligently"...
      */
-    if (r->status != HTTP_OK) {
-        recursive_error = type;
-
+    if (recursive_error != HTTP_OK) {
         while (r_1st_err->prev && (r_1st_err->prev->status != HTTP_OK))
             r_1st_err = r_1st_err->prev;  /* Get back to original error */
 
@@ -140,6 +142,11 @@ AP_DECLARE(void) ap_die(int type, reques
 
         custom_response = NULL; /* Do NOT retry the custom thing! */
     }
+    else {
+        int error_index = ap_index_of_response(type);
+        custom_response = ap_response_code_string(r, error_index);
+        recursive_error = 0;
+    }
 
     r->status = type;
 
@@ -215,6 +222,11 @@ AP_DECLARE(void) ap_die(int type, reques
     ap_send_error_response(r_1st_err, recursive_error);
 }
 
+AP_DECLARE(void) ap_die(int type, request_rec *r)
+{
+    ap_die_r(type, r, r->status);
+}
+
 static void check_pipeline_flush(request_rec *r)
 {
     apr_bucket *e;
@@ -283,18 +295,7 @@ void ap_process_request(request_rec *r)
         }
     }
 
-    if (access_status == DONE) {
-        /* e.g., something not in storage like TRACE */
-        access_status = OK;
-    }
-
-    if (access_status == OK) {
-        ap_finalize_request_protocol(r);
-    }
-    else {
-        r->status = HTTP_OK;
-        ap_die(access_status, r);
-    }
+    ap_die_r(access_status, r, HTTP_OK);
 
     /*
      * We want to flush the last packet if this isn't a pipelining connection
@@ -543,8 +544,8 @@ AP_DECLARE(void) ap_internal_fast_redire
 
 AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
 {
-    request_rec *new = internal_internal_redirect(new_uri, r);
     int access_status;
+    request_rec *new = internal_internal_redirect(new_uri, r);
 
     /* ap_die was already called, if an error occured */
     if (!new) {
@@ -558,12 +559,7 @@ AP_DECLARE(void) ap_internal_redirect(co
             access_status = ap_invoke_handler(new);
         }
     }
-    if (access_status == OK) {
-        ap_finalize_request_protocol(new);
-    }
-    else {
-        ap_die(access_status, new);
-    }
+    ap_die(access_status, new);
 }
 
 /* This function is designed for things like actions or CGI scripts, when
@@ -584,15 +580,9 @@ AP_DECLARE(void) ap_internal_redirect_ha
         ap_set_content_type(new, r->content_type);
     access_status = ap_process_request_internal(new);
     if (access_status == OK) {
-        if ((access_status = ap_invoke_handler(new)) != 0) {
-            ap_die(access_status, new);
-            return;
-        }
-        ap_finalize_request_protocol(new);
-    }
-    else {
-        ap_die(access_status, new);
+        access_status = ap_invoke_handler(new);
     }
+    ap_die(access_status, new);
 }
 
 AP_DECLARE(void) ap_allow_methods(request_rec *r, int reset, ...)

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c Fri Jun  5 16:50:47 2015
@@ -850,19 +850,15 @@ static int proxy_handler(request_rec *r)
             case M_TRACE: {
                 int access_status;
                 r->proxyreq = PROXYREQ_NONE;
-                if ((access_status = ap_send_http_trace(r)))
-                    ap_die(access_status, r);
-                else
-                    ap_finalize_request_protocol(r);
+                access_status = ap_send_http_trace(r);
+                ap_die(access_status, r);
                 return OK;
             }
             case M_OPTIONS: {
                 int access_status;
                 r->proxyreq = PROXYREQ_NONE;
-                if ((access_status = ap_send_http_options(r)))
-                    ap_die(access_status, r);
-                else
-                    ap_finalize_request_protocol(r);
+                access_status = ap_send_http_options(r);
+                ap_die(access_status, r);
                 return OK;
             }
             default: {

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ajp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ajp.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ajp.c (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ajp.c Fri Jun  5 16:50:47 2015
@@ -174,13 +174,13 @@ static int ap_proxy_ajp_request(apr_pool
     apr_byte_t conn_reuse = 0;
     const char *tenc;
     int havebody = 1;
-    int output_failed = 0;
+    int client_failed = 0;
     int backend_failed = 0;
     apr_off_t bb_len;
     int data_sent = 0;
     int request_ended = 0;
     int headers_sent = 0;
-    int rv = 0;
+    int rv = OK;
     apr_int32_t conn_poll_fd;
     apr_pollfd_t *conn_poll;
     proxy_server_conf *psf =
@@ -256,10 +256,10 @@ static int ap_proxy_ajp_request(apr_pool
         if (status != APR_SUCCESS) {
             /* We had a failure: Close connection to backend */
             conn->close++;
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server,
                          "proxy: ap_get_brigade failed");
             apr_brigade_destroy(input_brigade);
-            return HTTP_BAD_REQUEST;
+            return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
         }
 
         /* have something */
@@ -390,7 +390,13 @@ static int ap_proxy_ajp_request(apr_pool
                             ap_log_error(APLOG_MARK, APLOG_DEBUG, status,
                                          r->server,
                                          "ap_get_brigade failed");
-                            output_failed = 1;
+                            if (APR_STATUS_IS_TIMEUP(status)) {
+                                rv = HTTP_REQUEST_TIME_OUT;
+                            }
+                            else if (status == AP_FILTER_ERROR) {
+                                rv = AP_FILTER_ERROR;
+                            }
+                            client_failed = 1;
                             break;
                         }
                         bufsiz = maxsize;
@@ -401,7 +407,8 @@ static int ap_proxy_ajp_request(apr_pool
                             ap_log_error(APLOG_MARK, APLOG_DEBUG, status,
                                          r->server,
                                          "apr_brigade_flatten failed");
-                            output_failed = 1;
+                            rv = HTTP_INTERNAL_SERVER_ERROR;
+                            client_failed = 1;
                             break;
                         }
                     }
@@ -513,7 +520,7 @@ static int ap_proxy_ajp_request(apr_pool
                                           "proxy: error processing body.%s",
                                           r->connection->aborted ?
                                           " Client aborted connection." : "");
-                            output_failed = 1;
+                            client_failed = 1;
                         }
                         data_sent = 1;
                         apr_brigade_cleanup(output_brigade);
@@ -540,7 +547,7 @@ static int ap_proxy_ajp_request(apr_pool
                                         output_brigade) != APR_SUCCESS) {
                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                                       "proxy: error processing end");
-                        output_failed = 1;
+                        client_failed = 1;
                     }
                     /* XXX: what about flush here? See mod_jk */
                     data_sent = 1;
@@ -554,23 +561,27 @@ static int ap_proxy_ajp_request(apr_pool
 
         /*
          * If connection has been aborted by client: Stop working.
-         * Nevertheless, we regard our operation so far as a success:
-         * So reset output_failed to 0 and set result to CMD_AJP13_END_RESPONSE
-         * But: Close this connection to the backend.
+         * Pretend we are done (data_sent) to avoid further processing.
          */
         if (r->connection->aborted) {
-            conn->close++;
-            output_failed = 0;
-            result = CMD_AJP13_END_RESPONSE;
-            request_ended = 1;
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "client connection aborted");
+            /* no response yet (or ever), set status for access log */
+            if (!headers_sent) {
+                r->status = HTTP_BAD_REQUEST;
+            }
+            client_failed = 1;
+            /* return DONE */
+            data_sent = 1;
+            break;
         }
 
         /*
          * We either have finished successfully or we failed.
          * So bail out
          */
-        if ((result == CMD_AJP13_END_RESPONSE) || backend_failed
-            || output_failed)
+        if ((result == CMD_AJP13_END_RESPONSE)
+                || backend_failed || client_failed)
             break;
 
         /* read the response */
@@ -592,14 +603,14 @@ static int ap_proxy_ajp_request(apr_pool
      */
     apr_brigade_cleanup(output_brigade);
 
-    if (backend_failed || output_failed) {
+    if (backend_failed || client_failed) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                     "proxy: Processing of request failed backend: %i, "
-                     "output: %i", backend_failed, output_failed);
+                     "Processing of request failed backend: %i, client: %i",
+                     backend_failed, client_failed);
         /* We had a failure: Close connection to backend */
-        conn->close++;
-        /* Return DONE to avoid error messages being added to the stream */
+        conn->close = 1;
         if (data_sent) {
+            /* Return DONE to avoid error messages being added to the stream */
             rv = DONE;
         }
     }
@@ -609,8 +620,8 @@ static int ap_proxy_ajp_request(apr_pool
         /* We had a failure: Close connection to backend */
         conn->close++;
         backend_failed = 1;
-        /* Return DONE to avoid error messages being added to the stream */
         if (data_sent) {
+            /* Return DONE to avoid error messages being added to the stream */
             rv = DONE;
         }
     }
@@ -659,6 +670,15 @@ static int ap_proxy_ajp_request(apr_pool
             rv = HTTP_INTERNAL_SERVER_ERROR;
         }
     }
+    else if (client_failed) {
+        int level = (r->connection->aborted) ? APLOG_DEBUG : APLOG_ERR;
+        ap_log_error(APLOG_MARK, level, status, r->server,
+                     "dialog with client %pI failed",
+                     r->connection->remote_addr);
+        if (rv == OK) {
+            rv = HTTP_BAD_REQUEST;
+        }
+    }
 
     /*
      * Ensure that we sent an EOS bucket thru the filter chain, if we already
@@ -666,14 +686,17 @@ static int ap_proxy_ajp_request(apr_pool
      * one to the brigade already (no longer making it empty). So we should
      * not do this in this case.
      */
-    if (data_sent && !r->eos_sent && APR_BRIGADE_EMPTY(output_brigade)) {
+    if (data_sent && !r->eos_sent && !r->connection->aborted
+            && APR_BRIGADE_EMPTY(output_brigade)) {
         e = apr_bucket_eos_create(r->connection->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(output_brigade, e);
     }
 
-    /* If we have added something to the brigade above, sent it */
-    if (!APR_BRIGADE_EMPTY(output_brigade))
-        ap_pass_brigade(r->output_filters, output_brigade);
+    /* If we have added something to the brigade above, send it */
+    if (!APR_BRIGADE_EMPTY(output_brigade)
+        && ap_pass_brigade(r->output_filters, output_brigade) != APR_SUCCESS) {
+        rv = AP_FILTER_ERROR;
+    }
 
     apr_brigade_destroy(output_brigade);
 

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_http.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_http.c Fri Jun  5 16:50:47 2015
@@ -383,7 +383,7 @@ static int stream_reqbody_chunked(apr_po
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return HTTP_BAD_REQUEST;
+            return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
         }
     }
 
@@ -518,7 +518,7 @@ static int stream_reqbody_cl(apr_pool_t
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return HTTP_BAD_REQUEST;
+            return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
         }
     }
 
@@ -647,7 +647,7 @@ static int spool_reqbody_cl(apr_pool_t *
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return HTTP_BAD_REQUEST;
+            return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
         }
     }
 
@@ -1000,7 +1000,7 @@ int ap_proxy_http_request(apr_pool_t *p,
                          " from %s (%s)",
                          p_conn->addr, p_conn->hostname ? p_conn->hostname: "",
                          c->remote_ip, c->remote_host ? c->remote_host: "");
-            return HTTP_BAD_REQUEST;
+            return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
         }
 
         apr_brigade_length(temp_brigade, 1, &bytes);

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_scgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_scgi.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_scgi.c (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_scgi.c Fri Jun  5 16:50:47 2015
@@ -421,8 +421,9 @@ static int pass_response(request_rec *r,
         }
     }
 
-    /* XXX: What could we do with that return code? */
-    (void)ap_pass_brigade(r->output_filters, bb);
+    if (ap_pass_brigade(r->output_filters, bb)) {
+        return AP_FILTER_ERROR;
+    }
 
     return OK;
 }

Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c (original)
+++ httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c Fri Jun  5 16:50:47 2015
@@ -1610,7 +1610,7 @@ int ssl_io_buffer_fill(request_rec *r, a
         if (rv) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                           "could not read request body for SSL buffer");
-            return HTTP_INTERNAL_SERVER_ERROR;
+            return ap_map_http_request_error(rv, HTTP_INTERNAL_SERVER_ERROR);
         }
 
         /* Iterate through the returned brigade: setaside each bucket

Modified: httpd/httpd/branches/2.2.x/server/core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/core.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/server/core.c (original)
+++ httpd/httpd/branches/2.2.x/server/core.c Fri Jun  5 16:50:47 2015
@@ -3839,7 +3839,7 @@ static int default_handler(request_rec *
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
                           "default_handler: ap_pass_brigade returned %i",
                           status);
-            return HTTP_INTERNAL_SERVER_ERROR;
+            return AP_FILTER_ERROR;
         }
     }
     else {              /* unusual method (not GET or POST) */

Modified: httpd/httpd/branches/2.2.x/server/error_bucket.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/error_bucket.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/server/error_bucket.c (original)
+++ httpd/httpd/branches/2.2.x/server/error_bucket.c Fri Jun  5 16:50:47 2015
@@ -61,6 +61,9 @@ AP_DECLARE(apr_bucket *) ap_bucket_error
     APR_BUCKET_INIT(b);
     b->free = apr_bucket_free;
     b->list = list;
+    if (!ap_is_HTTP_VALID_RESPONSE(error)) {
+        error = HTTP_INTERNAL_SERVER_ERROR;
+    }
     return ap_bucket_error_make(b, error, buf, p);
 }
 

Modified: httpd/httpd/branches/2.2.x/server/util_xml.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/util_xml.c?rev=1683808&r1=1683807&r2=1683808&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/server/util_xml.c (original)
+++ httpd/httpd/branches/2.2.x/server/util_xml.c Fri Jun  5 16:50:47 2015
@@ -55,6 +55,7 @@ AP_DECLARE(int) ap_xml_parse_input(reque
                                 READ_BLOCKSIZE);
 
         if (status != APR_SUCCESS) {
+            result = ap_map_http_request_error(status, HTTP_BAD_REQUEST);
             goto read_error;
         }