You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@apache.org on 2011/04/01 21:25:26 UTC

svn commit: r1087864 - in /httpd/httpd/trunk: CHANGES modules/proxy/mod_proxy_ajp.c

Author: jim
Date: Fri Apr  1 19:25:26 2011
New Revision: 1087864

URL: http://svn.apache.org/viewvc?rev=1087864&view=rev
Log:
  *) mod_proxy_ajp: Add support for 'ProxyErrorOverride on'. PR 50945.
     [Peter Pramberger <peter pramberger.at>, Jim Jagielski]

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

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1087864&r1=1087863&r2=1087864&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Fri Apr  1 19:25:26 2011
@@ -2,7 +2,10 @@
 
 Changes with Apache 2.3.12
 
-  *) mod_proxy_fcgi: Add support for 'ProxyErrorOverride on' PR 50913.
+  *) mod_proxy_ajp: Add support for 'ProxyErrorOverride on'. PR 50945.
+     [Peter Pramberger <peter pramberger.at>, Jim Jagielski]
+
+  *) mod_proxy_fcgi: Add support for 'ProxyErrorOverride on'. PR 50913.
      [Mark Montague <mark catseye.org>, Jim Jagielski]
 
   *) core: Change the APIs of ap_cfg_getline() and ap_cfg_getc() to return an

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c?rev=1087864&r1=1087863&r2=1087864&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c Fri Apr  1 19:25:26 2011
@@ -190,6 +190,8 @@ static int ap_proxy_ajp_request(apr_pool
     apr_size_t maxsize = AJP_MSG_BUFFER_SZ;
     int send_body = 0;
     apr_off_t content_length = 0;
+    int original_status = r->status;
+    const char *original_status_line = r->status_line;
 
     if (psf->io_buffer_size_set)
        maxsize = psf->io_buffer_size;
@@ -430,71 +432,104 @@ static int ap_proxy_ajp_request(apr_pool
                 if (status != APR_SUCCESS) {
                     backend_failed = 1;
                 }
+                else if ((r->status == 401) && conf->error_override) {
+                    const char *buf;
+                    const char *wa = "WWW-Authenticate";
+                    if ((buf = apr_table_get(r->headers_out, wa))) {
+                        apr_table_set(r->err_headers_out, wa, buf);
+                    } else {
+                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                                     "ap_proxy_ajp_request: origin server "
+                                     "sent 401 without WWW-Authenticate header");
+                    }
+                }
                 headers_sent = 1;
                 break;
             case CMD_AJP13_SEND_BODY_CHUNK:
                 /* AJP13_SEND_BODY_CHUNK: piece of data */
                 status = ajp_parse_data(r, conn->data, &size, &send_body_chunk_buff);
                 if (status == APR_SUCCESS) {
-                    /* AJP13_SEND_BODY_CHUNK with zero length
-                     * is explicit flush message
+                    /* If we are overriding the errors, we can't put the content
+                     * of the page into the brigade.
                      */
-                    if (size == 0) {
-                        if (headers_sent) {
-                            e = apr_bucket_flush_create(r->connection->bucket_alloc);
-                            APR_BRIGADE_INSERT_TAIL(output_brigade, e);
+                    if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) {
+                        /* AJP13_SEND_BODY_CHUNK with zero length
+                         * is explicit flush message
+                         */
+                        if (size == 0) {
+                            if (headers_sent) {
+                                e = apr_bucket_flush_create(r->connection->bucket_alloc);
+                                APR_BRIGADE_INSERT_TAIL(output_brigade, e);
+                            }
+                            else {
+                                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                                     "Ignoring flush message received before headers");
+                            }
                         }
                         else {
-                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                                 "Ignoring flush message received before headers");
-                        }
-                    }
-                    else {
-                        apr_status_t rv;
-
-                        e = apr_bucket_transient_create(send_body_chunk_buff, size,
-                                                    r->connection->bucket_alloc);
-                        APR_BRIGADE_INSERT_TAIL(output_brigade, e);
-
-                        if ((conn->worker->s->flush_packets == flush_on) ||
-                            ((conn->worker->s->flush_packets == flush_auto) &&
-                            ((rv = apr_poll(conn_poll, 1, &conn_poll_fd,
-                                             conn->worker->s->flush_wait))
-                                             != APR_SUCCESS) &&
-                              APR_STATUS_IS_TIMEUP(rv))) {
-                            e = apr_bucket_flush_create(r->connection->bucket_alloc);
+                            apr_status_t rv;
+    
+                            /* 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(r->status)
+                                    && ap_is_HTTP_ERROR(original_status)) {
+                                r->status = original_status;
+                                r->status_line = original_status_line;
+                            }
+    
+                            e = apr_bucket_transient_create(send_body_chunk_buff, size,
+                                                        r->connection->bucket_alloc);
                             APR_BRIGADE_INSERT_TAIL(output_brigade, e);
+    
+                            if ((conn->worker->s->flush_packets == flush_on) ||
+                                ((conn->worker->s->flush_packets == flush_auto) &&
+                                ((rv = apr_poll(conn_poll, 1, &conn_poll_fd,
+                                                 conn->worker->s->flush_wait))
+                                                 != APR_SUCCESS) &&
+                                  APR_STATUS_IS_TIMEUP(rv))) {
+                                e = apr_bucket_flush_create(r->connection->bucket_alloc);
+                                APR_BRIGADE_INSERT_TAIL(output_brigade, e);
+                            }
+                            apr_brigade_length(output_brigade, 0, &bb_len);
+                            if (bb_len != -1)
+                                conn->worker->s->read += bb_len;
                         }
-                        apr_brigade_length(output_brigade, 0, &bb_len);
-                        if (bb_len != -1)
-                            conn->worker->s->read += bb_len;
-                    }
-                    if (ap_pass_brigade(r->output_filters,
-                                        output_brigade) != APR_SUCCESS) {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                      "proxy: error processing body.%s",
-                                      r->connection->aborted ?
-                                      " Client aborted connection." : "");
-                        output_failed = 1;
+                        if (ap_pass_brigade(r->output_filters,
+                                            output_brigade) != APR_SUCCESS) {
+                            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                                          "proxy: error processing body.%s",
+                                          r->connection->aborted ?
+                                          " Client aborted connection." : "");
+                            output_failed = 1;
+                        }
+                        data_sent = 1;
+                        apr_brigade_cleanup(output_brigade);
                     }
-                    data_sent = 1;
-                    apr_brigade_cleanup(output_brigade);
                 }
                 else {
                     backend_failed = 1;
                 }
                 break;
             case CMD_AJP13_END_RESPONSE:
-                e = apr_bucket_eos_create(r->connection->bucket_alloc);
-                APR_BRIGADE_INSERT_TAIL(output_brigade, e);
-                if (ap_pass_brigade(r->output_filters,
-                                    output_brigade) != APR_SUCCESS) {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "proxy: error processing end");
-                    output_failed = 1;
+                /* If we are overriding the errors, we must not send anything to
+                 * the client, especially as the brigade already contains headers.
+                 * So do nothing here, and it will be cleaned up below.
+                 */
+                if (!conf->error_override || !ap_is_HTTP_ERROR(r->status)) {
+                    e = apr_bucket_eos_create(r->connection->bucket_alloc);
+                    APR_BRIGADE_INSERT_TAIL(output_brigade, e);
+                    if (ap_pass_brigade(r->output_filters,
+                                        output_brigade) != APR_SUCCESS) {
+                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                                      "proxy: error processing end");
+                        output_failed = 1;
+                    }
+                    /* XXX: what about flush here? See mod_jk */
+                    data_sent = 1;
                 }
-                /* XXX: what about flush here? See mod_jk */
-                data_sent = 1;
                 request_ended = 1;
                 break;
             default:
@@ -569,7 +604,18 @@ static int ap_proxy_ajp_request(apr_pool
                      "proxy: got response from %pI (%s)",
                      conn->worker->cp->addr,
                      conn->worker->s->hostname);
-        rv = OK;
+
+        if (conf->error_override && ap_is_HTTP_ERROR(r->status)) {
+            /* clear r->status for override error, otherwise ErrorDocument
+             * thinks that this is a recursive error, and doesn't find the
+             * custom error page
+             */
+            rv = r->status;
+            r->status = HTTP_OK;
+        }
+        else {
+            rv = OK;
+        }
     }
 
     if (backend_failed) {