Commit bbffc5c0 authored by Eric Covener's avatar Eric Covener
Browse files

PR60576: php-fpm broken w/ per-dir rewrites

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
parent 462a1455
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
                                                         -*- 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]

+29 −0
Original line number Diff line number Diff line
@@ -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>
+88 −11
Original line number Diff line number Diff line
@@ -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,7 +285,13 @@ 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)) {
 
        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 */
@@ -278,6 +301,7 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
                    *qs = '\0';
                }
            }
        }

        if (newfname) {
            newfname = ap_strchr(newfname, '/');
@@ -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 */
};