Bug 38864 - ProxyPassReverse fails in <Location>
ProxyPassReverse fails in <Location>
Status: NEEDINFO
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy
2.2.0
All All
: P2 enhancement with 1 vote (vote)
: ---
Assigned To: Apache HTTPD Bugs Mailing List
: FixedInTrunk, PatchAvailable
: 38865 (view as bug list)
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2006-03-06 16:00 UTC by Douglas Acheson
Modified: 2013-04-25 10:19 UTC (History)
1 user (show)



Attachments
patch (811 bytes, patch)
2009-12-25 07:31 UTC, Nick Kew
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Douglas Acheson 2006-03-06 16:00:19 UTC
I want to proxy (loadbalance) all jsp and frm requests to tomcat through the
proxy and LB modules, and I cannot.

  I have the proxying/LBing working correctly for the following:

<LocationMatch "/myproject">
  ProxyPass balancer://myCluster/myproject stickysession=JSESSIONID
  ProxyPassReverse balancer://myCluster/bpsproject
  Order Deny,Allow
  Allow from all
</LocationMatch>

Now, when I try to use a regular expression to proxy .jsp and .frm requests,
there is no proxying done all.  This is what I use:

<LocationMatch "^/myproject/.+\.(jsp|frm)$">
  ProxyPass        balancer://myCluster/myproject stickysession=JSESSIONID
  ProxyPassReverse balancer://myCluster/bpsproject
  Order Deny,Allow
  Allow from all
</LocationMatch>

In the error log I get a 404 error:
[Mon Mar 06 10:45:41 2006] [error] [client 10.0.0.152] File does not exist:
C:/dwfa/runtime/apache/httpd/html/myproject/login.jsp

I have tried this with win32 (got binary) and linux (built) with the same results.
Comment 1 Astrid Keßler 2006-03-06 20:20:49 UTC
*** Bug 38865 has been marked as a duplicate of this bug. ***
Comment 2 Douglas Acheson 2006-03-06 20:49:37 UTC
The configuration snipit is really
<LocationMatch "^/myproject/.+\.(jsp|frm)$">
  ProxyPass        balancer://myCluster/myproject stickysession=JSESSIONID
  ProxyPassReverse balancer://myCluster/myproject
  Order Deny,Allow
  Allow from all
</LocationMatch>

I had a typo in the one originally posted.  Still have tht same issue
Comment 3 Ruediger Pluem 2006-03-06 21:24:32 UTC
ProxyPass does not work with regular expressions. Thus it does not work inside
LocationMatch. Apart from the discussion if this is a bug and if yes if it is a
bug in the documentation or in the code you can use mod_rewrite to solve your
problem:

RewriteEngine on
RewriteRule (^/myproject/.+\.(jsp|frm)$) balancer://myCluster$1

<Proxy balancer://myCluster>
BalancerMember http://127.0.0.1:8080
BalancerMember http://127.0.0.1:8081 
ProxySet stickysession=JSESSIONID
</Proxy>

ProxyPassReverse /myproject http://127.0.0.1:8080/myproject
ProxyPassReverse /myproject http://127.0.0.1:8081/myproject

Please keep in mind that you MUST use ProxySet AFTER the BalancerMember directives.

Comment 4 Douglas Acheson 2006-03-08 19:36:39 UTC
Thx your for your reply.  A couple of things:

1. I could not find, but does not mean it does not exist, documentation about
proxy and REs.  But, if it does not work, so be it.

2.  Not sure why LocationMatch and proxy work to tightly.  Here is my simple
view of how I thought it should work:
  if the incoming URL matches the grammar supplied by the RE in LocationMatch
    do the work (in this case proxy the request)
I do not understand why proxy needs to know about RE as, IMHO, only
LocationMatch needs to do the patching.

3. I really appreciate an alternate solution.  I have tried that and it does not
work (as I expect).  If I take what you supplied I get tomcat serving up
everything (jsp, gif, etc).  So I went and read up on RewriteRule and found out
that I should use the [p] token at the end of the "rule".  When I tried this,
nothing works.  So I am really confused now.

4.  I do not understand why the ProxyPassReverse is written in that manor.  Why
does it use http as the protocol and why must I specify every member?  Should I
not be able to use balancer as the protocol.

4.  Since my original defect report,t in all honestly has been resolved, I
understand if you want to close this ticket.

Here is my new snippet I used:

<IfDefine rewrite>
  RewriteEngine On
 
  <Proxy balancer://myCluster>
    BalancerMember ajp://10.0.0.152:8009 loadfactor=100 route=152
    BalancerMember ajp://10.0.0.153:8009 loadfactor=100 route=153
    ProxySet stickysession=JSESSIONID
    Order Deny,Allow
    Allow from all
  </Proxy>

  RewriteRule (^/myproject/.+\.(jsp|html|form))  balancer://myCluster$0
  #RewriteRule (^/myproject/.+\.(jsp|html|form)) balancer://myCluster$0 [p]

  ProxyPassReverse /myproject http://10.0.0.152:8080/myproject
  ProxyPassReverse /myproject http://10.0.0.153:8080/myproject

  <Location /balancer-manager>
    SetHandler balancer-manager
    Order Deny,Allow
    Allow from all
  </Location>

</IfDefine>
Comment 5 Ruediger Pluem 2006-03-08 20:37:00 UTC
(In reply to comment #4)

> 
> 2.  Not sure why LocationMatch and proxy work to tightly.  Here is my simple
> view of how I thought it should work:
>   if the incoming URL matches the grammar supplied by the RE in LocationMatch
>     do the work (in this case proxy the request)
> I do not understand why proxy needs to know about RE as, IMHO, only
> LocationMatch needs to do the patching.

That is due to how the internal processing works. I admit that this is not
logical from a users perspective view. Basicly a ProxyPass inside a Location or
LocationMatch container is transformed to ProxyPass <string of
Locationcontainer> <proxytarget> during the parsing of the configuration. So in
your example this gets transformed to
ProxyPass ^/myproject/.+\.(jsp|frm)$ balancer://myCluster/myproject
Stickysession=JSESSIONID

As ProxyPass does not know anything about RE it tries to match the URL plain
against ^/myproject/.+\.(jsp|frm)$ which cannot work for obvious reasons.

> 
> 3. I really appreciate an alternate solution.  I have tried that and it does not
> work (as I expect).  If I take what you supplied I get tomcat serving up
> everything (jsp, gif, etc).  So I went and read up on RewriteRule and found 
out
> that I should use the [p] token at the end of the "rule".  When I tried this,

Ah, sorry a copy and paste error from my side. It should have been

RewriteRule (^/myproject/.+\.(jsp|frm)$) balancer://myCluster$1 [P]

Astonishing that this worked at all without the [P] flag.

> nothing works.  So I am really confused now.

It should work. I tested it in my environment. You have an error in your config
(see below)

> 
> 4.  I do not understand why the ProxyPassReverse is written in that manor.  Why
> does it use http as the protocol and why must I specify every member?  Should I
> not be able to use balancer as the protocol.

No. ProxyPassReverse works like a lookup table. It checks possible Location
headers of the HTTP responses from the backend and transforms them into the
correct ones (by using the lookup table) to make redirects work. But the backend
servers do know nothing about the balancer scheme. So they put in their local
name (http://127.0.0.1:8080 and http://127.0.0.1:8081 in your case) in their
Location headers.


> 
>   RewriteRule (^/myproject/.+\.(jsp|html|form))  balancer://myCluster$0
>   #RewriteRule (^/myproject/.+\.(jsp|html|form)) balancer://myCluster$0 [p]

The error is $0 at the end. It must be $1. Please use the line with the [P] flag
at the end.

Comment 6 Douglas Acheson 2006-03-09 15:33:08 UTC
Thanks I got it working.  Appreciate all your help ...
Comment 7 Steve Madsen 2009-02-16 08:59:32 UTC
This bug is marked resolved and fixed, but it doesn't work in the current 2.2.11 release. ProxyPassReverse, in particular, still does not function inside LocationMatch as an end-user expects it to after reading the 2.2 documentation.

I'm trying to account for case sensitivity on a proxied prefix, e.g.:

<LocationMatch ^(?i)/foo/>
    ProxyPassReverse http://foo.backend.server/
</LocationMatch>

Per http://www.apachetutor.org/admin/reverseproxies, ProxyPassReverse should be set up like this to account for broken applications that issue a redirect using only the path instead of a full URL.

Mainly I'm interested in clarification on this bug. Should it work? If so, there is a regression in the current stable release.

If it is known not to work and there is no intention to fix it, I think the documentation should be updated to explicitly state that the directives do not work inside Location using the ~ syntax or in LocationMatch.
Comment 8 Nick Kew 2009-12-23 16:36:54 UTC
(In reply to comment #7)
> This bug is marked resolved and fixed, but it doesn't work in the current
> 2.2.11 release. ProxyPassReverse, in particular, still does not function inside
> LocationMatch as an end-user expects it to after reading the 2.2 documentation.

You have indeed found a rather serious regression.

It's actually in mod_proxy, and can be worked around by replacing your
ProxyPassReverse /
with
ProxyPassReverse balancer:///
(note three slashes are not a typo)!  It doesn't matter that you're not using the balancer - this is just a failure in the parsing of the URL in the response header.

Not sure when this happened, but it appears to go back quite some time.
Guess I need to fix both the code and the tutorial!
Comment 9 Nick Kew 2009-12-25 07:28:31 UTC
Just fixed in trunk in r893871
Will upload patch in a moment.
Comment 10 Nick Kew 2009-12-25 07:31:18 UTC
Created attachment 24757 [details]
patch

trunk patch, works with 2.2.x versions.
Comment 11 Nick Kew 2009-12-25 14:17:21 UTC
(In reply to comment #8)
> (In reply to comment #7)
> > This bug is marked resolved and fixed, but it doesn't work in the current
> > 2.2.11 release. ProxyPassReverse, in particular, still does not function inside
> > LocationMatch as an end-user expects it to after reading the 2.2 documentation.
> 
> You have indeed found a rather serious regression.

... which is not the problem you were asking about - sorry for the distraction, and thanks to rpluem for pointing it out.  I might look at that too, but supporting regexps is new code, and more likely to happen in 2.3/2.4 (which alreasy supports regexps in related areas like ProxyPass).
Comment 12 Christoph Anton Mitterer 2012-12-08 23:58:37 UTC
Quite some time old...

Could someone tell me whether this is still an issue?
Comment 13 alessandro natapin 2013-02-14 22:22:28 UTC
the directive ProxyPassReverse works correctly also in the form 
"ProxyPassReverse /" inside <Location>. Just tested with Location containing full URL. I couldn't reproduce the buggy case with just path in location header.
The Apache version used is 2.4.3

As regard the error got with ProxyPassReverse inside <LocationMatch>, it is not correct to set it as bug, because, as stated in the offcial documentation, the RE is not treated as such by ProxyPassReverse 

".... When used inside a <Location> section, the first argument is omitted and the local directory is obtained from the <Location>. The same occurs inside a <LocationMatch> section, but will probably not work as intended, as ProxyPassReverse will interpret the regexp literally as a path;...."

So I find correct to set this item as enhancement. It should be closed when a sort of ProxyPassReverseMatch will be implemented.