Bug 62477 - ProxyPassInterpolateEnv causes config syntax failures at startup
Summary: ProxyPassInterpolateEnv causes config syntax failures at startup
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.5-HEAD
Hardware: PC Mac OS X 10.1
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-06-21 08:15 UTC by Luca Toscano
Modified: 2018-06-22 12:19 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Luca Toscano 2018-06-21 08:15:27 UTC
While playing with the following config (in httpd trunk) I got:

ProxyPassInterpolateEnv On
SetEnvIf "Test" "bla" proxy_port=8000

<Location /test>
     ProxyPass "http://localhost:${proxy_port}/test" interpolate
</Location>

[Thu Jun 21 08:11:29.304425 2018] [core:warn] [pid 21013:tid 140441193370688] AH00111: Config variable ${proxy_port} is not defined
AH00526: Syntax error on line 224 of /usr/local/apache2/conf/httpd.conf:
ProxyPass Unable to parse URL: http://localhost:${proxy_port}/test
httpd: abnormal exit 1

But if I move the ${proxy_port} outside scheme://host:port then httpd starts up as expected.

https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass says:

"""
The optional interpolate keyword, in combination with ProxyPassInterpolateEnv, causes the ProxyPass to interpolate environment variables, using the syntax ${VARNAME}. Note that many of the standard CGI-derived environment variables will not exist when this interpolation happens, so you may still have to resort to mod_rewrite for complex rules. Also note that interpolation is not supported within the scheme portion of a URL. Dynamic determination of the scheme can be accomplished with mod_rewrite as in the following example.
"""

Didn't check in the code why this is the behavior, but either the code or the docs are a bit misleading/wrong.
Comment 1 Luca Toscano 2018-06-21 14:41:44 UTC
The issue to me seems that ap_proxy_define_worker uses apr_uri_parse that fails to parse things like ${variable}, and since it happens as a consequence of ProxyPass directives getting parsed it can be effectively usable only by variables already present at early startup, like the ones set by Define (that indeed work fine).

It might be possible to delay this operation but not sure if it is worth. As far as I understand ProxyPassInterpolateEnv seems not really usable at the moment, but I might miss something. Feedback welcome :)
Comment 2 Luca Toscano 2018-06-22 08:15:33 UTC
As a quick test, commenting apr_uri_parse seems to make everything work fine (of course not a solution, but the fix might be trivial).

ap_proxy_define_worker, afaics, is called when ProxyPass is parsed but also during runtime if a (proxy) worker is not found, so the comment above simply delays the whole process to runtime. So a possible solution is to not be strict in URI parsing when the interpolate flag is used, since there may be variables not yet resolved, but need to check a bit more the code before being sure. Feedback welcome!
Comment 3 Luca Toscano 2018-06-22 08:57:34 UTC
(In reply to Luca Toscano from comment #2)
> As a quick test, commenting apr_uri_parse seems to make everything work fine
> (of course not a solution, but the fix might be trivial).

Better: commenting the check for the return value of apr_uri_parse:

    rv = apr_uri_parse(p, url, &uri);

    /*if (rv != APR_SUCCESS) {
        return apr_pstrcat(p, "Unable to parse URL: ", url, NULL);
    }*/
Comment 4 Yann Ylavic 2018-06-22 09:30:37 UTC
If the scheme and hostname part of the URI can't be parsed, there is really no point to define a worker, no load time characteristic allowing connections management (e.g. reuse) for the same origin server, hence every connection will be handled by the default "reverse-proxy" worker.

So the real hostname has to be declared somehow (e.g. <Proxy scheme://realhostname>), and at this point as the doc you pointed to says: "If you require a more flexible reverse-proxy configuration, see the RewriteRule directive with the [P] flag".
Comment 5 Luca Toscano 2018-06-22 09:50:34 UTC
Hi Yann!

I agree 100%, my question is (and this is me not familiar enough with the worker workflow) if the proxy definition can be deferred to later on when the proxy variable will be available, since I saw in various pieces of code that if the worker is not found it can be defined and then used. Or is it necessary to create/define it when the ProxyPass directive is parsed (so during httpd's startup) ?

In any case, the error message is misleading in my opinion.. If we want to restrict variable usage with interpolate then a trace of this restriction should be found by a user when httpd logs the error, not in the docs :)
Comment 6 Luca Toscano 2018-06-22 12:16:04 UTC
Sorry now I get what you were saying. If you have to defer the creation of the worker based on a per request variable, then there is no point in defining a "one off" worker / connection-pool. My naive view of the conn pool / worker was that it would have been defined the first time by the first request value populating the variable, and then re-used across requests, this is why I was asking the question about deferring the worker initialization.

IIUC, either a worker is well defined at "startup" time, or the default worker will be used. I am wondering if a more precise error message for the user when apr_uri_parse fails and 'interpolate' is set might help (like "hey there, please remember that you are not allowed to add variables for scheme/hostname/port"). If my understanding is right I'd also like to add an explanation in the docs, from my point of view it is not really clear.
Comment 7 Yann Ylavic 2018-06-22 12:19:40 UTC
Yes, a better error message and doc looks sensible, +1.