https://issues.apache.org/bugzilla/show_bug.cgi?id=55415

            Bug ID: 55415
           Summary: Proxy loop caused by ProxyErrorOverride and
                    ErrorDocument 404
           Product: Apache httpd-2
           Version: 2.4.6
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: mod_proxy_fcgi
          Assignee: [email protected]
          Reporter: [email protected]

1. Overview Description

  If ProxyErrorOverride is On, proxy's not found error page should be
  overridden by ErrorDocument 404. But actually a proxy loop occurs
  if ErrorDocument 404 points to a url of FastCGI server script.

  The following is my test environment for this issue.

  - apache 2.4.6
  - mod_proxy_fcgi (reverse proxy)
  - php-fpm (PHP 5.5.1, FastCGI server)

  And these directives were added to httpd.conf to forward requests for php
scripts.

  [ httpd.conf ]
  ErrorDocument 404 /error.php
  ProxyErrorOverride On
  ProxyPassMatch ^/(.+\.php)$ fcgi://localhost:9010/home/httpd/htdocs/$1

  This is the content of error.php.

  [ error.php ]
  <?php
  echo "No such file.<br>";

  In the environment, when I accessed a url that does not exist,
  I got the next message after a while without overriding by ErrorDocument 404.

  [ error page ]
  Not Found
  The requested URL /xxx.php was not found on this server.
  Additionally, a 500 Internal Server Error error was encountered
  while trying to use an ErrorDocument to handle the request.

  And I got the following message in apache's error_log at the same time.

  [ error_log ]
  [Wed Aug 14 17:46:33.144561 2013] [proxy_fcgi:error] [pid 29478:tid
1111763264] [client 192.168.1.46:2322] AH01071: Got error 'Primary script
unknown\n'
  [Wed Aug 14 17:46:37.258829 2013] [core:error] [pid 29478:tid 1111763264]
[client 192.168.1.46:2322] AH00124: Request exceeded the limit of 10 internal
redirects due to probable configuration error. Use 'LimitInternalRecursion' to
increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

  Besides, in access_log of FastCGI server, I got ten success messages for
error.php.

  [ access_log ]
  192.168.1.46  [14/08/2013:17:46:33 +0900] "GET /error.php" 200 0.325 256
0.00% "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/28.0.1500.95 Safari/537.36"
  ...
  (10 times)

  In short, even though each ErrorDocument's request is success,
  it is repeated until reaching ProxyMaxForwards's default value(10). 

  I checked modules/proxy/mod_proxy_fcgi.c to find the cause of this behavior
  and found that sending ErrorDocument is controlled by script_error_status in
  dispatch().

  First script_error_status is initialized with HTTP_OK in dispatch().

  [ dispatch() ]
  551     int script_error_status = HTTP_OK;

  When you access a url that does not exist on FastCGI server,
  r->status has been NotFound(404).

  Next, only in case that ProxyErrorOverride is On and r->status is error,
  r->status's value(404) is assigned to script_error_status and r->status
  is set to HTTP_OK.

  [ dispatch() ]
  759                             if (conf->error_override &&
  760                                 ap_is_HTTP_ERROR(r->status)) {
  761                                 /*
  762                                  * set script_error_status to discard
  763                                  * everything after the headers
  764                                  */
  765                                 script_error_status = r->status;
  766                                 /*
  767                                  * prevent ap_die() from treating this as
a
  768                                  * recursive error, initially:
  769                                  */
  770                                 r->status = HTTP_OK;
  771                             }

  Because script_error_status(404) is not HTTP_OK, ap_die() is called
  to send ErrorDocument.

  [ dispatch() ]
  865     if (script_error_status != HTTP_OK) {
  866         ap_die(script_error_status, r); /* send ErrorDocument */
  867     }

  In ap_die() of modules/http/http_request.c, r->status is rewritten
  with scrip_error_status's value(404).

  [ ap_die() ]
   76 AP_DECLARE(void) ap_die(int type, request_rec *r)
  ...
  144
  145     r->status = type;
  146

  Because ErrorDocument points to local url, ap_internal_redirect() is called.

  [ ap_die() ]
  181         else if (custom_response[0] == '/') {
  ...
  200             r->method = "GET";
  201             r->method_number = M_GET;
  202             ap_internal_redirect(custom_response, r);
  203             return;
  204         }

  r->status's value(404) is kept until this request reaches
  to dispatch() of mod_proxy_fcgi.c.

  Because dispatch() has no code that initializes r->status's value(404),
  script_error_status's value will be 404 again and internal forwarding
  is repeated until ProxyMaxForwards's value again.

  It seems that this is why the proxy loop occurs.

2. Steps to Reproduce

  1) Run FastCGI(php-fpm) server on localhost:9010.
     Its document root is /home/httpd/htdocs.

  2) Place error.php in the document root.
     <?php
     echo "No such file.<br>";

  3) Add these directives to httpd.conf.
    ErrorDocument 404 /error.php
    ProxyErrorOverride On
    ProxyPassMatch ^/(.+\.php)$ fcgi://localhost:9010/home/httpd/htdocs/$1

  4) Start or restart Apache2.

  5) Access a url that does not exist.
    http://FQDN/not_exist.html
    A proxy loop will be detected.

3. Actual Results

  A proxy loop occurs.

4. Expected Results

  FastCGI's not found error page is overrided by ErrorDocument 404.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to