On Fri, Aug 2, 2024 at 3:26 PM Eric Covener <cove...@gmail.com> wrote:
>
> On Fri, Aug 2, 2024 at 9:10 AM Yann Ylavic <ylavic....@gmail.com> wrote:
> >
> > On Fri, Aug 2, 2024 at 1:06 PM Eric Covener <cove...@gmail.com> wrote:
> > >
> > > > Yeah, if not under DocumentRoot I don't see how ProxyPass could work,
> > > > but SetHandler should since it's following the whole request
> > > > processing to resolve the filesystem r->filename?
> > >
> > > In the examples I am seeing spot-checking google results, people who
> > > use ProxyPass + FPM hard-code the document root (or wherever the stuff
> > > is) in the 2nd parameter. This includes our own manual and the
> > > unofficial confluence wiki.
> >
> > Ah ok, I think we can do something like this:
> >         if (rconf->need_dirwalk) {
> >             const char *docroot = ap_document_root(r);
> >             if (strncmp(docroot, r->filename, strlen(docroot)) != 0) {
> >                 r->proxyreq = PROXYREQ_NONE;
> >                 ap_core_translate(r);
> >             }
> >             ap_directory_walk(r);
> >         }
> > ?
>
> I think users could be happily humming along with some other absolute
> filesystem path in the ProxyPass 2nd arg and would now see it
> docroot-prefixed.
> Are you trying to make the ProxyPass+FPM vars better because they will
> no longer be fixed up by apache_was_here side effects? I think it is
> probably bes to just retain/restore some of the historical bogus
> values if MAY_BE_FPM -- maybe doing them at the last moment where we'd
> do the above.

Maybe this:
    if (rconf) {
        if (!rconf->need_dirwalk) {
            r->filename = rconf->filename;
        }
        else {
            char *saved_uri = r->uri;
            char *saved_path_info = r->path_info;
            int i = 0;

            /* Try to find the script without DocumentRoot than with */
            do {
                r->path_info = NULL;
                r->filename = r->uri = rconf->filename;
                if (i) {
                    r->proxyreq = PROXYREQ_NONE;
                    ap_core_translate(r);
                    r->proxyreq = PROXYREQ_REVERSE;
                }
                ap_directory_walk(r);
            } while (r->finfo.filetype != APR_REG && ++i < 2);

            /* If no actual script was found, fall back to the "proxy:"
             * SCRIPT_FILENAME dealt with below or by php-fpm directly.
             */
            if (i == 2) {
                r->path_info = saved_path_info;
                r->filename = proxy_filename;
            }
            /* Restore REQUEST_URI in any case */
            r->uri = saved_uri;
        }
    }
?
Index: modules/proxy/mod_proxy_fcgi.c
===================================================================
--- modules/proxy/mod_proxy_fcgi.c	(revision 1919628)
+++ modules/proxy/mod_proxy_fcgi.c	(working copy)
@@ -29,6 +29,7 @@ typedef struct {
 
 typedef struct {
     int need_dirwalk;
+    char *filename;
 } fcgi_req_config_t;
 
 /* We will assume FPM, but still differentiate */
@@ -141,8 +142,10 @@ static int proxy_fcgi_canon(request_rec *r, char *
         rconf = apr_pcalloc(r->pool, sizeof(fcgi_req_config_t));
         ap_set_module_config(r->request_config, &proxy_fcgi_module, rconf);
     }
+    rconf->filename = apr_pstrcat(r->pool, "/", url, NULL);
 
-    if (NULL != (pathinfo_type = apr_table_get(r->subprocess_env, "proxy-fcgi-pathinfo"))) {
+    pathinfo_type = apr_table_get(r->subprocess_env, "proxy-fcgi-pathinfo");
+    if (pathinfo_type) {
         /* It has to be on disk for this to work */
         if (!strcasecmp(pathinfo_type, "full")) {
             rconf->need_dirwalk = 1;
@@ -181,6 +184,9 @@ static int proxy_fcgi_canon(request_rec *r, char *
                     "set r->path_info to %s", r->path_info);
         }
     }
+    else if (FCGI_MAY_BE_FPM(dconf) && !from_handler) {
+        rconf->need_dirwalk = 1;
+    }
 
     return OK;
 }
@@ -359,16 +365,43 @@ static apr_status_t send_environment(proxy_conn_re
     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);
+    char *proxy_filename = r->filename;
 
-    if (rconf && rconf->need_dirwalk) {
-        char *saved_filename = r->filename;
-        r->filename = r->uri;
-        ap_directory_walk(r);
-        r->filename = saved_filename;
+    if (rconf) {
+        if (!rconf->need_dirwalk) {
+            r->filename = rconf->filename;
+        }
+        else {
+            char *saved_uri = r->uri;
+            char *saved_path_info = r->path_info;
+            int i = 0;
+
+            /* Try to find the script without DocumentRoot than with */
+            do {
+                r->path_info = NULL;
+                r->filename = r->uri = rconf->filename;
+                if (i) {
+                    r->proxyreq = PROXYREQ_NONE;
+                    ap_core_translate(r);
+                    r->proxyreq = PROXYREQ_REVERSE;
+                }
+                ap_directory_walk(r);
+            } while (r->finfo.filetype != APR_REG && ++i < 2);
+
+            /* If no actual script was found, fall back to the "proxy:"
+             * SCRIPT_FILENAME dealt with below or by php-fpm directly.
+             */
+            if (i == 2) {
+                r->path_info = saved_path_info;
+                r->filename = proxy_filename;
+            }
+            /* Restore REQUEST_URI in any case */
+            r->uri = saved_uri;
+        }
     }
 
-    /* Strip proxy: prefixes */
-    if (r->filename) {
+    /* Strip "proxy:" prefixes? */
+    if (r->filename == proxy_filename) {
         char *newfname = NULL;
 
         if (!strncmp(r->filename, "proxy:balancer://", 17)) {
@@ -401,6 +434,8 @@ static apr_status_t send_environment(proxy_conn_re
     ap_add_common_vars(r);
     ap_add_cgi_vars(r);
 
+    r->filename = proxy_filename;
+
     /* XXX are there any FastCGI specific env vars we need to send? */
 
     /* Give admins final option to fine-tune env vars */

Reply via email to