summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Covener <covener@apache.org>2017-01-11 20:58:33 +0000
committerEric Covener <covener@apache.org>2017-01-11 20:58:33 +0000
commit728cb09d13b44451594803a9619619a12fc3c2ca (patch)
tree0e267ad147ba1c5f120aa0a356b30af387aade70
parent18e99a8f198e5fd52e222ec80efad11f676105fc (diff)
downloadhttpd-728cb09d13b44451594803a9619619a12fc3c2ca.tar.gz
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
-rw-r--r--CHANGES6
-rw-r--r--docs/manual/mod/mod_proxy_fcgi.xml29
-rw-r--r--modules/proxy/mod_proxy_fcgi.c99
3 files changed, 123 insertions, 11 deletions
diff --git a/CHANGES b/CHANGES
index 49b5a9d2d2..57ffe5a196 100644
--- 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]
diff --git a/docs/manual/mod/mod_proxy_fcgi.xml b/docs/manual/mod/mod_proxy_fcgi.xml
index 30cfb7b306..9cdeddfa8d 100644
--- a/docs/manual/mod/mod_proxy_fcgi.xml
+++ b/docs/manual/mod/mod_proxy_fcgi.xml
@@ -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>
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 397a1a7782..b291dae341 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -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 */
};