From ff92f0de85e3111e65fd817992535b08b43e438e Mon Sep 17 00:00:00 2001 From: Eric Covener Date: Wed, 14 Jan 2015 13:28:47 +0000 Subject: [PATCH] Merge r1647035 from trunk: provide alternative PATH_INFO calculation options for proxy_fcgi. PR 55329 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1651663 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++ docs/manual/mod/mod_proxy_fcgi.xml | 22 +++++++++- modules/proxy/mod_proxy_fcgi.c | 66 +++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 8714492413..3b2282233b 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,10 @@ Changes with Apache 2.4.11 request headers earlier. Adds "MergeTrailers" directive to restore legacy behavior. [Edward Lu, Yann Ylavic, Joe Orton, Eric Covener] + *) mod_proxy_fcgi: Provide some basic alternate options for specifying + how PATH_INFO is passed to FastCGI backends by adding significance to + the value of proxy-fcgi-pathinfo. PR 55329. [Eric Covener] + *) mod_proxy_fcgi: Enable UDS backends configured with SetHandler/RewriteRule to opt-in to connection reuse and other Proxy options via explicitly declared "proxy workers" (Script-URI and be compliant with RFC 3875 section 3.3. If instead you need mod_proxy_fcgi to generate a "best guess" for PATH_INFO, set this env-var. - This is a workaround for a bug in some FCGI implementations. + This is a workaround for a bug in some FCGI implementations. This + variable can be set to multiple values to tweak at how the best guess + is chosen: +
+
first-dot
+
PATH_INFO is split from the slash following the + first "." in the URL.
+
last-dot
+
PATH_INFO is split from the slash following the + last "." in the URL.
+
full
+
PATH_INFO is calculated by an attempt to map the URL to the + local filesystem.
+
unescape
+
PATH_INFO is the path component of the URL, unescaped / + decoded.
+
any other value
+
PATH_INFO is the same as the path component of the URL. + Originally, this was the only proxy-fcgi-pathinfo option.
+
+ diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c index 54a4e8dc48..f528b3dfdd 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -20,6 +20,10 @@ module AP_MODULE_DECLARE_DATA proxy_fcgi_module; +typedef struct { + int need_dirwalk; +} fcgi_req_config_t; + /* * Canonicalise http-like URLs. * scheme is the scheme for the URL @@ -29,8 +33,11 @@ module AP_MODULE_DECLARE_DATA proxy_fcgi_module; static int proxy_fcgi_canon(request_rec *r, char *url) { char *host, sport[7]; - const char *err, *path; + const char *err; + char *path; apr_port_t port, def_port; + fcgi_req_config_t *rconf = NULL; + const char *pathinfo_type = NULL; if (strncasecmp(url, "fcgi:", 5) == 0) { url += 5; @@ -76,11 +83,51 @@ static int proxy_fcgi_canon(request_rec *r, char *url) ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01060) "set r->filename to %s", r->filename); - if (apr_table_get(r->subprocess_env, "proxy-fcgi-pathinfo")) { - r->path_info = apr_pstrcat(r->pool, "/", path, NULL); + rconf = ap_get_module_config(r->request_config, &proxy_fcgi_module); + if (rconf == NULL) { + rconf = apr_pcalloc(r->pool, sizeof(fcgi_req_config_t)); + ap_set_module_config(r->request_config, &proxy_fcgi_module, rconf); + } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01061) - "set r->path_info to %s", r->path_info); + if (NULL != (pathinfo_type = apr_table_get(r->subprocess_env, "proxy-fcgi-pathinfo"))) { + /* It has to be on disk for this to work */ + if (!strcasecmp(pathinfo_type, "full")) { + rconf->need_dirwalk = 1; + ap_unescape_url_keep2f(path, 0); + } + else if (!strcasecmp(pathinfo_type, "first-dot")) { + char *split = ap_strchr(path, '.'); + if (split) { + char *slash = ap_strchr(split, '/'); + if (slash) { + r->path_info = apr_pstrdup(r->pool, slash); + ap_unescape_url_keep2f(r->path_info, 0); + *slash = '\0'; /* truncate path */ + } + } + } + else if (!strcasecmp(pathinfo_type, "last-dot")) { + char *split = ap_strrchr(path, '.'); + if (split) { + char *slash = ap_strchr(split, '/'); + if (slash) { + r->path_info = apr_pstrdup(r->pool, slash); + ap_unescape_url_keep2f(r->path_info, 0); + *slash = '\0'; /* truncate path */ + } + } + } + else { + /* before proxy-fcgi-pathinfo had multi-values. This requires the + * the FCGI server to fixup PATH_INFO because it's the entire path + */ + r->path_info = apr_pstrcat(r->pool, "/", path, NULL); + if (!strcasecmp(pathinfo_type, "unescape")) { + ap_unescape_url_keep2f(r->path_info, 0); + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01061) + "set r->path_info to %s", r->path_info); + } } return OK; @@ -205,12 +252,19 @@ 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; char *proxyfilename = r->filename; + fcgi_req_config_t *rconf = ap_get_module_config(r->request_config, &proxy_fcgi_module); + + if (rconf) { + if (rconf->need_dirwalk) { + ap_directory_walk(r); + } + } /* Strip balancer prefix */ if (r->filename && !strncmp(r->filename, "proxy:balancer://", 17)) { char *newfname = apr_pstrdup(r->pool, r->filename+17); newfname = ap_strchr(newfname, '/'); - r->filename = newfname; + r->filename = newfname; } ap_add_common_vars(r); -- 2.40.0