You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2010/02/13 21:24:25 UTC

svn commit: r909899 - in /httpd/httpd/trunk: CHANGES modules/proxy/mod_proxy_http.c

Author: minfrin
Date: Sat Feb 13 20:24:24 2010
New Revision: 909899

URL: http://svn.apache.org/viewvc?rev=909899&view=rev
Log:
mod_proxy_http: Make sure that when an ErrorDocument is served
from a reverse proxied URL, that the subrequest respects the status
of the original request. This brings the behaviour of proxy_handler
in line with default_handler. PR 47106.

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/proxy/mod_proxy_http.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=909899&r1=909898&r2=909899&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sat Feb 13 20:24:24 2010
@@ -2,6 +2,11 @@
 
 Changes with Apache 2.3.7
 
+  *) mod_proxy_http: Make sure that when an ErrorDocument is served
+     from a reverse proxied URL, that the subrequest respects the status
+     of the original request. This brings the behaviour of proxy_handler
+     in line with default_handler. PR 47106. [Graham Leggett]
+
   *) Support wildcards in both the directory and file components of
      the path specified by the Include directive. [Graham Leggett]
 

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_http.c?rev=909899&r1=909898&r2=909899&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_http.c Sat Feb 13 20:24:24 2010
@@ -1368,6 +1368,10 @@
         {"Keep-Alive", "Proxy-Authenticate", "TE", "Trailer", "Upgrade", NULL};
     int i;
     const char *te = NULL;
+    int original_status = r->status;
+    int proxy_status = OK;
+    const char *original_status_line = r->status_line;
+    const char *proxy_status_line = NULL;
 
     bb = apr_brigade_create(p, c->bucket_alloc);
     pass_bb = apr_brigade_create(p, c->bucket_alloc);
@@ -1481,7 +1485,7 @@
 
             keepchar = buffer[12];
             buffer[12] = '\0';
-            r->status = atoi(&buffer[9]);
+            proxy_status = atoi(&buffer[9]);
 
             if (keepchar != '\0') {
                 buffer[12] = keepchar;
@@ -1492,8 +1496,13 @@
                 buffer[12] = ' ';
                 buffer[13] = '\0';
             }
-            r->status_line = apr_pstrdup(p, &buffer[9]);
+            proxy_status_line = apr_pstrdup(p, &buffer[9]);
 
+            /* The status out of the front is the same as the status coming in
+             * from the back, until further notice.
+             */
+            r->status = proxy_status;
+            r->status_line = proxy_status_line;
 
             /* read the headers. */
             /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/
@@ -1569,7 +1578,7 @@
             if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
                 ap_set_content_type(r, apr_pstrdup(p, buf));
             }
-            if (!ap_is_HTTP_INFO(r->status)) {
+            if (!ap_is_HTTP_INFO(proxy_status)) {
                 ap_proxy_pre_http_request(origin, rp);
             }
 
@@ -1620,7 +1629,7 @@
             backend->close += 1;
         }
 
-        if (ap_is_HTTP_INFO(r->status)) {
+        if (ap_is_HTTP_INFO(proxy_status)) {
             interim_response++;
         }
         else {
@@ -1659,7 +1668,7 @@
          * ProxyPassReverse/etc from here to ap_proxy_read_headers
          */
 
-        if ((r->status == 401) && (conf->error_override)) {
+        if ((proxy_status == 401) && (conf->error_override)) {
             const char *buf;
             const char *wa = "WWW-Authenticate";
             if ((buf = apr_table_get(r->headers_out, wa))) {
@@ -1699,8 +1708,8 @@
         /* send body - but only if a body is expected */
         if ((!r->header_only) &&                   /* not HEAD request */
             !interim_response &&                   /* not any 1xx response */
-            (r->status != HTTP_NO_CONTENT) &&      /* not 204 */
-            (r->status != HTTP_NOT_MODIFIED)) {    /* not 304 */
+            (proxy_status != HTTP_NO_CONTENT) &&      /* not 204 */
+            (proxy_status != HTTP_NOT_MODIFIED)) {    /* not 304 */
 
             /* We need to copy the output headers and treat them as input
              * headers as well.  BUT, we need to do this before we remove
@@ -1726,11 +1735,22 @@
              * if we are overriding the errors, we can't put the content
              * of the page into the brigade
              */
-            if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) {
+            if (!conf->error_override || !ap_is_HTTP_ERROR(proxy_status)) {
                 /* read the body, pass it to the output filters */
                 apr_read_type_e mode = APR_NONBLOCK_READ;
                 int finish = FALSE;
 
+                /* Handle the case where the error document is itself reverse
+                 * proxied and was successful. We must maintain any previous
+                 * error status so that an underlying error (eg HTTP_NOT_FOUND)
+                 * doesn't become an HTTP_OK.
+                 */
+                if (conf->error_override && !ap_is_HTTP_ERROR(proxy_status)
+                        && ap_is_HTTP_ERROR(original_status)) {
+                    r->status = original_status;
+                    r->status_line = original_status_line;
+                }
+
                 do {
                     apr_off_t readbytes;
                     apr_status_t rv;
@@ -1847,25 +1867,27 @@
 
     if (conf->error_override) {
         /* the code above this checks for 'OK' which is what the hook expects */
-        if (!ap_is_HTTP_ERROR(r->status))
+        if (!ap_is_HTTP_ERROR(proxy_status)) {
             return OK;
+        }
         else {
             /* clear r->status for override error, otherwise ErrorDocument
              * thinks that this is a recursive error, and doesn't find the
              * custom error page
              */
-            int status = r->status;
             r->status = HTTP_OK;
             /* Discard body, if one is expected */
             if (!r->header_only && /* not HEAD request */
-                (status != HTTP_NO_CONTENT) && /* not 204 */
-                (status != HTTP_NOT_MODIFIED)) { /* not 304 */
-               ap_discard_request_body(rp);
-           }
-            return status;
+                (proxy_status != HTTP_NO_CONTENT) && /* not 204 */
+                (proxy_status != HTTP_NOT_MODIFIED)) { /* not 304 */
+                ap_discard_request_body(rp);
+            }
+            return proxy_status;
         }
-    } else
+    }
+    else {
         return OK;
+    }
 }
 
 static