]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
PR60576: php-fpm broken w/ per-dir rewrites
authorEric Covener <covener@apache.org>
Wed, 11 Jan 2017 20:58:33 +0000 (20:58 +0000)
committerEric Covener <covener@apache.org>
Wed, 11 Jan 2017 20:58:33 +0000 (20:58 +0000)
Attempt to dig out of well-meaning fixes for generic fcgi backends
that negatively affected some FPM configs.

Adds ProxyFCGIBackendType

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1778350 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_proxy_fcgi.xml
modules/proxy/mod_proxy_fcgi.c

diff --git a/CHANGES b/CHANGES
index 49b5a9d2d2c3e12c573b6c516cfae3b8d02b3665..57ffe5a196a4495197581e97c7096cdf15ecce30 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,12 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_proxy_fcgi: Return to 2.4.20-and-earlier behavior of leaving 
+     a "proxy:fcgi://" prefix in the SCRIPT_FILENAME environment variable by 
+     default.  Add ProxyFCGIBackendType to allow the type of backend to be
+     specified so these kinds of fixups can be restored without impacting
+     FPM. PR60576 [Eric Covener]
+
   *) Don't set SO_REUSEPORT unless ListenCoresBucketsRatio is greater
      than zero.  [Eric Covener]
 
index 30cfb7b306a8ef3a974a89308b8fa8f6f8375c4e..9cdeddfa8d41f759135850e97a5219dbfd12e6ff 100644 (file)
@@ -195,4 +195,33 @@ ProxyPass "/myapp/" "balancer://myappcluster/"
     </dl>
 </section>
 
+<directivesynopsis>
+<name>ProxyFCGIBackendType</name>
+<description>Specify the type of backend FastCGI application</description>
+<syntax>ProxyFCGIBackendType FPM|GENERIC</syntax>
+<default>ProxyFCGIBackendType FPM</default>
+<contextlist><context>server config</context>
+<context>virtual host</context><context>directory</context>
+<context>.htaccess</context></contextlist>
+<compatibility>Available in version 2.5 and later</compatibility>
+
+<usage>
+<p>This directive allows the type of backend FastCGI application to be
+specified. Some FastCGI servers, such as PHP-FPM,  use historical quirks of
+environment variables to identify the type of proxy server being used.  Set
+this direcive to "GENERIC" if your non PHP-FPM application has trouble
+interpreting environment variables such as SCRIPT_FILENAME or PATH_TRANSLATED
+as set by the server.</p>
+
+<p>One example of values that change based on the setting of this directive is
+SCRIPT_FILENAME. When using <module>mod_proxy_fcgi</module> historically,
+SCRIPT_FILENAME was prefixed with the string "proxy:fcgi://". This variable is
+what some generic FastCGI applications would read as their script input, but
+PHP-FPM would strip the prefix then remember it was talking to Apache.  In
+2.4.21 through 2.4.25, this prefix was automatically stripped by the server,
+breaking the ability of PHP-FPM to detect and interoperate with Apache in some
+scenarios.</p> 
+</usage>
+</directivesynopsis>
+
 </modulesynopsis>
index 397a1a778265f9bb95867e0b491d7a539bb150bf..b291dae34111624c8f000b3ca79478b54d2f089f 100644 (file)
@@ -24,6 +24,22 @@ typedef struct {
     int need_dirwalk;
 } fcgi_req_config_t;
 
+/* We will assume FPM, but still differentiate */
+typedef enum {
+    BACKEND_DEFAULT_UNKNOWN = 0,
+    BACKEND_FPM,
+    BACKEND_GENERIC,
+} fcgi_backend_t;
+
+#define FCGI_MAY_BE_FPM(dconf)                              \
+        (dconf &&                                           \
+        ((dconf->backend_type == BACKEND_DEFAULT_UNKNOWN) || \
+        (dconf->backend_type == BACKEND_FPM)))
+
+typedef struct {
+    fcgi_backend_t backend_type;
+} fcgi_dirconf_t;
+
 /*
  * Canonicalise http-like URLs.
  * scheme is the scheme for the URL
@@ -254,6 +270,7 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
     apr_size_t avail_len, len, required_len;
     int next_elem, starting_elem;
     fcgi_req_config_t *rconf = ap_get_module_config(r->request_config, &proxy_fcgi_module);
+    fcgi_dirconf_t *dconf = ap_get_module_config(r->per_dir_config, &proxy_fcgi_module);
 
     if (rconf) { 
        if (rconf->need_dirwalk) { 
@@ -268,14 +285,21 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
         if (!strncmp(r->filename, "proxy:balancer://", 17)) {
             newfname = apr_pstrdup(r->pool, r->filename+17);
         }
-        else if (!strncmp(r->filename, "proxy:fcgi://", 13)) {
-            newfname = apr_pstrdup(r->pool, r->filename+13);
-        }
-        /* Query string in environment only */
-        if (newfname && r->args && *r->args) { 
-            char *qs = strrchr(newfname, '?');
-            if (qs && !strcmp(qs+1, r->args)) { 
-                *qs = '\0';
+        if (!FCGI_MAY_BE_FPM(dconf))  { 
+            if (!strncmp(r->filename, "proxy:fcgi://", 13)) {
+                /* If we strip this under FPM, and any internal redirect occurs 
+                 * on PATH_INFO, FPM may use PATH_TRANSLATED instead of 
+                 * SCRIPT_FILENAME (a la mod_fastcgi + Action).
+                 */
+                newfname = apr_pstrdup(r->pool, r->filename+13);
+            }
+            /* Query string in environment only */
+            if (newfname && r->args && *r->args) { 
+                char *qs = strrchr(newfname, '?');
+                if (qs && !strcmp(qs+1, r->args)) { 
+                    *qs = '\0';
+                }
             }
         }
 
@@ -976,18 +1000,71 @@ cleanup:
     return status;
 }
 
+static void *fcgi_create_dconf(apr_pool_t *p, char *path)
+{
+    fcgi_dirconf_t *a;
+
+    a = (fcgi_dirconf_t *)apr_pcalloc(p, sizeof(fcgi_dirconf_t));
+    a->backend_type = BACKEND_DEFAULT_UNKNOWN;
+    return a;
+}
+
+static void *fcgi_merge_dconf(apr_pool_t *p, void *basev, void *overridesv)
+{
+    fcgi_dirconf_t *a, *base, *over;
+
+    a     = (fcgi_dirconf_t *)apr_pcalloc(p, sizeof(fcgi_dirconf_t));
+    base  = (fcgi_dirconf_t *)basev;
+    over  = (fcgi_dirconf_t *)overridesv;
+
+    a->backend_type = (over->backend_type != BACKEND_DEFAULT_UNKNOWN) 
+                      ? over->backend_type 
+                      : base->backend_type;
+    return a;
+}
+
+
+static const char *cmd_servertype(cmd_parms *cmd, void *in_dconf,
+                                   const char *val)
+{
+    fcgi_dirconf_t *dconf = in_dconf;
+    
+    if (!val || !*val) { 
+        return "ProxyFCGIBackendType requires one  of the following arguments: "
+               "'GENERIC', 'PHP-FPM'";
+    } 
+
+    if (!strcasecmp(val, "GENERIC")) { 
+       dconf->backend_type = BACKEND_GENERIC;
+    }
+    else if (!strcasecmp(val, "FPM") || !strcasecmp(val, "PHP-FPM")) { 
+       dconf->backend_type = BACKEND_FPM;
+    }
+    else { 
+        return "ProxyFCGIBackendType requires one  of the following arguments: "
+               "'GENERIC', 'PHP-FPM'";
+    }
+
+    return NULL;
+}
+
 static void register_hooks(apr_pool_t *p)
 {
     proxy_hook_scheme_handler(proxy_fcgi_handler, NULL, NULL, APR_HOOK_FIRST);
     proxy_hook_canon_handler(proxy_fcgi_canon, NULL, NULL, APR_HOOK_FIRST);
 }
+static const command_rec command_table[] = {
+    AP_INIT_TAKE1(    "ProxyFCGIBackendType",   cmd_servertype,  NULL, OR_FILEINFO,
+                     " Specify the type of FastCGI server: 'Generic' 'FPM'"),
+    { NULL }
+};
 
 AP_DECLARE_MODULE(proxy_fcgi) = {
     STANDARD20_MODULE_STUFF,
-    NULL,                       /* create per-directory config structure */
-    NULL,                       /* merge per-directory config structures */
+    fcgi_create_dconf,          /* create per-directory config structure */
+    fcgi_merge_dconf,           /* merge per-directory config structures */
     NULL,                       /* create per-server config structure */
     NULL,                       /* merge per-server config structures */
-    NULL,                       /* command apr_table_t */
+    command_table,              /* command apr_table_t */
     register_hooks              /* register hooks */
 };