Forum Moderators: phranque

Message Too Old, No Replies

Infinite loop with rewrite and proxy

         

drosowski

6:14 pm on Nov 6, 2009 (gmt 0)

10+ Year Member



Hello there,

first of all thanks for this great forum, it already helped me a lot. But now I'm stuck.
I have the following scenario. I have a CMS system which is running on localhost:8080. Then I have a web application running in a tomcat server on localhost:8081. I want to be able to access the CMS simply by going to www.mydomain.com. The webapp should be accessible as www.mydomain.com/webapp. I solved it using mod_rewrite like so:

RewriteEngine on
RewriteCond %{REQUEST_URI} ^/webapp/?(.*)$ [NC]
RewriteRule ^(.*) http://localhost:8081/$1 [L,P]
ProxyPassReverse /webapp http://localhost:8081

RewriteRule ^(.*)$ http://localhost:8080/$1 [L,P]

It seeems like everything works fine, since the webapp wants to redirect me to the starting, but doesn't succeed. The browser says it cannot load the page due to too much redirects.

Does this sound familiar to anybody? Your help is greatly appreciated!

Cheers,
Daniel

[edited by: jdMorgan at 9:09 pm (utc) on Nov. 6, 2009]
[edit reason] De-linked [/edit]

jdMorgan

6:31 pm on Nov 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The first rule proxies /webapp/<whatever> to localhost:8081/webapp/<whatever>
The second rule proxies <anything> to localhost:8081/<anything> and therefore proxies anything that the first rule does not, making the first rule utterly redundant.

So your code doesn't make sense, and leaves me confused.

Please define what you are trying to accomplish in terms of client requested URLs and what you wish to do with them -- i.e. whether they should be proxied, and if so, where they should be proxied to.

We also need to know *what* redirect your back-end is doing in order to diagnose the larger problem. Remember that a redirect terminates the current HTTP transaction, and tells the client to make a new request using the Location specified in the redirect response. In addition, the server has no "memory" of this redirect response, and so the client request in response to the redirect is seen as a completely-new transaction, and all of your rules and directives will run again.

Jim

drosowski

7:45 pm on Nov 6, 2009 (gmt 0)

10+ Year Member



Jim,
Ok, I'll try to be more specific. Apache should act as a frontend to both the CMS application and another web application running on a tomcat server.
So if the client is requesting http://www.mydomain.com it should be proxied to http://localhost:8080.
Whereas if the client is requesting http://www.mydomain.com/myapp it should be proxied to http://localhost:8081.

And I thought that's what the rewriting rules are saying. The first rule says proxy /webbapp to localhost:8081/webapp. If the rule applies apache won't execute any other rule, because of the last(L) flag, right? The second rule proxies everything else to the "normal" website, which is a CMS system running at localhost:8080. I don't quite understand why that makes the first rule redundant.

The back-end (the webapp at localhost:8081) redirects the client to www.mydomain.com/webapp/control/main.

Here's an excerpt from apaches access.log, where the problem gets quite obvious.

First the client's requesting /webapp:
xx.xx.xx.xx - - [06/Nov/2009:19:10:36 +0100] "GET /webapp HTTP/1.1" 302 - "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)"

And then the webapp redirects the client to /webapp/control/main. This line gets repeated a couple of dozen times.
xx.xx.xx.xx - - [06/Nov/2009:19:10:37 +0100] "GET /webapp/control/main HTTP/1.1" 302 - "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)"

I just can't figure out the right way to do it.

Cheers,
Daniel

[edited by: jdMorgan at 9:08 pm (utc) on Nov. 6, 2009]
[edit reason] de-linked [/edit]

jdMorgan

9:06 pm on Nov 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Sorry, I missed the 8080 vs. 8081.

However, because of HTTP redirection functioning as I explained above, the [L] flag does not have the effect you wish, because after the client is redirected it issues a whole new HTTP request and your code starts over.

So, your patterns are not specific enough (the first proxies) /webapp<anything> as noted above and the second proxies <anything at all>.

Again, you have not been specific in describing your URL-space (a common problem, since people aren't used to thinking about it in this way), so I'll give you a very-restrictive solution that will work only for the URLs you've specified:


ProxyPassReverse /webapp http://localhost:8081
#
RewriteEngine on
#
RewriteCond %{REQUEST_URI} !^/webapp/control/main
RewriteRule ^/(.*)$ http://localhost:8081/$1 [P]
#
RewriteRule ^/myapp/(.*)$ http://localhost:8080/$1 [P]

Note that [P] implies [L], so [L] is redundant.

I'm assuming this code goes into your server config file (e.g. httpd.conf) not inside a <Directory> container or into a .htaccess file. If this asumption is not correct, remove the leading slash from the RewriteRule patterns only.

Note also that your redirect is a 302 not a 301. Be sure that's what you want, as this tells the search engines to keep the original URL and not replace it with the redirection target URL. In fact, you should ask yourself whether a redirect is necessary or desirable, because, as outlined above, this requires a second request by the client, and will therefore slow down the user experience and clog up your log files with two HTTP requests per user page-load.

Also based on the original order of your directives, it may be useful for you to know that "code" in your config files is not executed in line-by-line order as a sequential "program." Instead each Apache module in turn parses (scans) the file for directives that it understands, and executes only those. So the module execution order determines which directives get executed first, not the code order in the file. Module execution order is controlled by the LoadModule list order (reversed) in Apache 1.x, and by an internal priority scheme in Apache 2.x.

Jim

drosowski

6:49 pm on Nov 8, 2009 (gmt 0)

10+ Year Member



Thanks for the example you provided. After all I got it working with the following configuration:

RewriteCond %{REQUEST_URI} ^/webapp/?(.*)$ [NC]
RewriteRule ^(.*) [localhost:8081...] [P]
ProxyPassReverse /webapp [localhost:8081...]
RewriteRule ^(.*)$ [localhost:8080...] [P]

Thanks for your help!
Cheers,
Daniel