Bug 60458 - ProxyPass in a Location block loops on local ErrorDocument
Summary: ProxyPass in a Location block loops on local ErrorDocument
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.4.23
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
Keywords: FixedInTrunk
Depends on:
Reported: 2016-12-09 00:37 UTC by Alexandre Schaff
Modified: 2017-04-05 11:12 UTC (History)
1 user (show)

potential fix (1.46 KB, patch)
2016-12-09 01:04 UTC, Eric Covener
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexandre Schaff 2016-12-09 00:37:49 UTC
(Finally :o) Upgrading from 2.2, I have either a regression or the same "behavior change" as commented in https://bz.apache.org/bugzilla/show_bug.cgi?id=54319.

Please update based on following details.

This conf is added to fresh 2.4.23 build with minimal set of modules ( mpm worker )
# =======BEGIN
ErrorDocument 400 /error/unavailable
ErrorDocument 401 /error/empty
ErrorDocument 403 /error/forbidden
ErrorDocument 404 /error/unavailable

ProxyErrorOverride On
Alias /error "/tmp/error"
ProxyPass /error !

<Directory "/tmp/error">
 AllowOverride None
 Require all granted

ProxyPass /
ProxyPassReverse /
# ========= END

"Server" on responds with status 403, no body.
The configuration above works as expected.

If ProxyPass(Reverse) directives are in a Location block : (rest of configuration unchanged)....
# =======BEGIN
 <Location />
     Require all granted
# ========= END

... then an internal requests loop starts until LimitInternalRecursion (10) is reached. Client receives latest 403 response, a status 500 is recorded in access_log.

note : the same configuration (using Order+Allow instead of Require ) on a fresh minimal build of 2.2.31 works as expected.

Comment 1 Eric Covener 2016-12-09 01:04:46 UTC
Created attachment 34509 [details]
potential fix

potential fix, untested. Iterates over server conf to check for ! entries.
Comment 2 Eric Covener 2016-12-09 01:05:02 UTC
Are you able to test a patch?
Comment 3 Alexandre Schaff 2016-12-09 08:55:49 UTC
(In reply to Eric Covener from comment #2)
> Are you able to test a patch?

Fix applied and tested 2.4.23.
On that single test, the behavior is consistent with 2.2 : no more internal loop.

Thanks Eric.

Note : component changed from core to mod_proxy.
Comment 4 Jim Jagielski 2016-12-09 13:33:00 UTC
If this affects trunk, we should fold in there and then propose a back port to 2.4
Comment 5 Eric Covener 2016-12-31 00:27:05 UTC
Fixed in 2.4.25
Comment 6 Eric Covener 2017-01-30 12:56:14 UTC
FYI this caused a regression, it may be reverted in the next 2.4 release. After re-reviewing the PR, a better answer may have been "don't put it in <Location> if you want to have an exception before it.

Bug in the fix aside, one of the points of ProxyPass in <Location> is that it's a single proxy rule for a location.  So the server-scoped rules, even exceptions, do not "come first".
Comment 7 Michael H 2017-04-05 11:12:32 UTC
Hello, we upgraded from 2.4.18 to 2.4.25 and now our configuration isn't working anymore.

   ProxyPreserveHost On

   <Proxy balancer://ppp>
      BalancerMember http://xxx.xx.xx.xx:8080 route=vm_0 ping=5
      BalancerMember http://xxx.xx.xx.xx:8080 route=vm_1 ping=5

   <Location "/service">
     ProxyPass balancer://ppp/system stickysession=JSESSIONID|jsessionid scolonpathdelim=On
     ProxyPassReverse balancer://ppp/system
     ProxyPassReverse http://ppp.local/system
     ProxyPassReverse https://ppp.local/system
     ProxyPassReverseCookiePath /system /service

   ProxyPass /error !
   ProxyPass /manager !
   ProxyPass / balancer://asp/ stickysession=JSESSIONID|jsessionid scolonpathdelim=On
   ProxyPassReverse / balancer://ppp/

With 2.4.25 all requests are routet through the last ProxyPass, the Location directive is ignored so the rewrite from the context is not happening.
Can this be due to this change?

If i put the last ProxyPass in a Location directive like <Location ~ "^/(?!service)"> it's also working.

Thanks in Advance