Apache Rewrite to a Location - apache

We have a single web application that handles different URL formats and returns the same content in a different formats.
/dosomething
/foo/dosomething (returns mobile content)
/bar/dosomething (returns html for a browser)
See the sample Virtual Host below.
For Apache 2.2, I used Rewrite Rules to redirect http://www.foobarbaz.net/dosomething to the Location "/baz/" which functioned as I expected.
The "PT" flag on the RewriteRule passed the URI back to Apache and allowed us to serve content from the "baz" location.
<VirtualHost *:80>
ServerName www.foobarbaz.net
RewriteEngine On
#Block requests for favicon
RewriteRule ^/favicon.ico$ - [F]
# If the requested URI is NOT located in bar or foo
# Prepend an /baz to everything that does not already starts with it
# and force the result to be handled by the next URI-handler ([PT])
RewriteCond %{REQUEST_URI} !^/bar/.*$
RewriteCond %{REQUEST_URI} !^/foo/.*$
RewriteRule ^/(.*) /baz/$1 [PT,QSA]
<Location "/baz/">
RequestHeader append ABC-Request-Origin "/baz"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /
</Location>
<Location "/bar/">
RequestHeader append ABC-Request-Origin "/bar"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /bar/
</Location>
<Location "/foo/">
RequestHeader append ABC-Request-Origin "/foo"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /foo/
</Location>
</VirtualHost>
For Apache 2.4.12, the Rewrite Rules do not function in the same manner and Apache tries to find the content on the file system. Apache looks for a "baz" directory which does not exist.
I tried adding another location "/" and removing the rewrite rules (see below).
The docs indicate that for overlapping Locations, the least specific should go first.
http://httpd.apache.org/docs/current/sections.html
This works for "/", but not for "/foo/" or "/bar". It seems that "/" is always used and "foo" and "bar" are always included in the request to the p.roxy
<VirtualHost *:80>
ServerName www.foobarbaz.net
<Location "/">
RequestHeader append ABC-Request-Origin "/baz"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /
</Location>
<Location "/bar/">
RequestHeader append ABC-Request-Origin "/bar"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /bar/
</Location>
<Location "/foo/">
RequestHeader append ABC-Request-Origin "/foo"
ProxyPass ajp://localhost:8009/webapp/
ProxyPassReverse /
ProxyPassReverseCookiePath /webapp /foo/
</Location>
</VirtualHost>
Does anyone have suggestions on how to improve this setup? Or suggestions on handling requests to "/" differently that "/foo" or "/bar"
Thanks for any help.
Jim

It appears that using a Location "/" first does properly use the Locations for "/", "/foo" and "/bar" I do have other issues related to building links in the application, but I do not believe it is an Apache issue.

Related

Bad redirection of Mattermost docker behind reverse proxy apache2

I am trying to install the docker version of Mattermost on my Ubuntu 14.04 with apache2 version 2.4.7.
Here is the configuration of mattermost-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName www.my.website.fr
ServerAlias website.fr
DocumentRoot /home/www/www-website
[...]
<Proxy *>
Require all granted
</Proxy>
ProxyPreserveHost On
ProxyRequests Off
RewriteEngine on
ProxyPass /mattermost http://localhost:8083
ProxyPassReverse /mattermost http://localhost:8083
RewriteCond %{REQUEST_URI} /api/v[0-9]+/(users/)?websocket [NC,OR]
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://127.0.0.1:8083%{REQUEST_URI} [P,QSA,L]
<Location /home/www/www-soft/mattermost>
Require all granted
ProxyPass http://127.0.0.1:8083/
ProxyPassReverse http://127.0.0.1:8083/
</Location>
[...]
</VirtualHost>
</IfModule>
The website is accessible but nothing appears on the page, because I got such error messages (one example among several others of the same form):
Failed to load resource: the server responded with a status of 404 (Not Found) https://www.my.website.fr/static/main.9e27a2872d73987ea8ec.css
Instead of trying to access the file at:
https://www.my.website.fr/mattermost/static/main.9e27a2872d73987ea8ec.css (which exists, I tested)
(I replaced my website domain by "my.website.fr")
Is there any obvious reason why the apache proxy is not redirecting correctly with the /mattermost prefix ? Am I missing something ?
The dedicated page in Mattermost documentation didn't help me much resolving this (https://docs.mattermost.com/install/config-apache2.html)
From apache documentation: https://httpd.apache.org/docs/2.4/mod/core.html#location
The directive limits the scope of the enclosed directives
by URL.
Which means you need to change:
<Location /home/www/www-soft/mattermost>
Require all granted
ProxyPass http://127.0.0.1:8083/
ProxyPassReverse http://127.0.0.1:8083/
</Location>
to
<Location /mattermost>
Require all granted
ProxyPass http://127.0.0.1:8083/
ProxyPassReverse http://127.0.0.1:8083/
</Location>
Because your document root is set to
DocumentRoot /home/www/www-website
You're also using proxypass to handle requests to the same path
ProxyPass /mattermost http://localhost:8083
ProxyPassReverse /mattermost http://localhost:8083
You need to chose which solution you want to implement: both might not work well together.
At last, you're also using
ProxyPreserveHost On
which I'm not sure it's needed/working as you think: please refer to https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypreservehost to find out if it's realy required in your environment.

Apache 2.2 reverse-proxy behind Nexus 3

The apache server is configure with following items :
<VirtualHost *:80>
...
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /jenkins/ http://localhost:8080/ timeout=300
ProxyHTMLURLMap http://localhost:8080 /jenkins
<Location /jenkins/>
ProxyPassReverse /
ProxyHTMLEnable On
ProxyHTMLExtended On
ProxyHTMLURLMap / /jenkins/ [L]
RequestHeader unset Accept-Encoding
</Location>
ProxyPass /nexus/ http://localhost:8081/ timeout=300
ProxyHTMLURLMap http://localhost:8081 /nexus
<Location /nexus/>
ProxyPassReverse /
ProxyHTMLEnable On
ProxyHTMLExtended On
ProxyHTMLURLMap / /nexus/ [L]
RequestHeader unset Accept-Encoding
</Location>
ProxyVia On
</IfModule>
Jenkins proxy works fine.
Nexus proxy load the page but cannot load resources. The HTML page ressources are not defined with the right path, instead of myhost.domain/nexus/static/... the URLs are myhost.domain/static/.... What's going wrong in the configuration ?
The solution is to switch Nexus context path configuration to '/nexus/'. In general, it seems that the nexus context path must match the proxy context path.

Mod_proxy rewrite rule help for /foo/ to /foo/index.html

With mod_proxy I need to redirect /foo/ requests to /foo/index.html. So if a user types in : https://example.com/foo/ they should be redirected to https://example.com/foo/index.html
I tried the following rule but it does not work:
<Location /foo/>
RequestHeader set Host example.com
</Location>
ProxyPass /foo/ https://example.com/foo/index.html
ProxyPassReverse /foo/ https://example.com/foo/index.html
While this works for any requests to https://example.com/foo/*, it does not work for https://example.com/foo/. Any help on what I can use for the redirect to work correctly?
You need to add a normal redirect to index.html before the request hits the proxy.
<Location /foo/>
RequestHeader set Host example.com
</Location>
RewriteRule ^/foo(/|)$ /foo/index.html [NC]
ProxyPass /foo/ https://example.com/foo/
ProxyPassReverse /foo/ https://example.com/foo/

ProxyPass and DocumentRoot on one domain

Let's say I have the following configuration:
<VirtualHost domain.com>
# Server names, admins, logs etc...
ProxyVia On
ProxyRequests Off
<Location "/">
ProxyPass http://localhost:8080/tomcat-webapp/
ProxyPassReverse http://localhost:8080/tomcat-webapp/
Order allow,deny
Allow from all
</Location>
</VirtualHost>
Now, I want the address domain.com/forum to display content of my MyBB forum, which has its files inside the /var/www/forum directory. How to accomplish this?
Actually, I resolved this problem with the following code:
ProxyPass /forum !
ProxyPass / http://localhost:8080/tomcat-webapp/
ProxyPassReverse / http://localhost:8080/tomcat-webapp/
Alias /forum /var/www/forum
What it is recommending is using mod_rewrite to perform the ProxyPass instead of ProxyPass/ProxyPassReverse command.
Try something like:
RewriteRule ^/forum - [L]
RewriteRule ^/(.*) http://localhost:8080/tomcat-webapp/$1 [P,L]
ProxyPassReverse / http://localhost:8080/tomcat-webapp/
I use:
<VirtualHost *:80>
#other irrelevant configs here
ProxyPass /forum http://localhost:8080/myBB
ProxyPassReverse /forum http://localhost:8080/myBB
ProxyPass / http://localhost:8081/tomcat-app
ProxyPassReverse / http://localhost:8081/tomcat-app
</VirtualHost>
You don't have to say "tomcat-app" if your tomcat app is the root app.

Apache proxying subdomain root requests

Description
Internal Tomcat server that has webapps listening on 8080:
"http://internal:8080/foo-webservice/"
"http://internal:8080/foo-website/"
External facing Apache server is proxying requests for a subdomain:
"http://foo.domain.com/"
Any requests of the root of the subdomain would be proxied to the foo-website webapp on Tomcat.
Any other requests would be proxied to the appropriate path / webapp
Use Case A
Request:
"http://foo.domain.com/index.html"
Proxied to:
"http://internal:8080/foo-website/index.html"
Use Case B
Request:
"http://foo.domain.com/webservice/listener.html?param1=foo&param2=bar"
Proxied to:
"http://internal:8080/foo-webservice/listener.html?param1=foo&param2=bar"
VirtualHost definition
Current virtual host definition which satisfies Use Case B:
<VirtualHost *:80>
ServerName foo.domain.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ErrorLog /var/log/apache2/foo_error.log
LogLevel warn
CustomLog /var/log/apache2/foo_access.log combined
# RewriteRules
# ?
# ProxyPass
ProxyPreserveHost On
ProxyPass / http://internal:8080/
ProxyPassReverse / http://internal:8080/
</VirtualHost>
Attempt 1
# RewriteRules
RewriteEngine On
RewriteRule ^/(.*) http://internal:8080/foo-website/$1 [P]
Use Case A is satisfied
Use Case B fails
Attempt 2
# RewriteRules
RewriteEngine On
RewriteRule ^/$ http://internal:8080/foo-website/$1 [P]
Use Case B is satisfied
Use Case A is not completely satisfied
The index.html in foo-website is loaded, but none of the files in the js, img or css folders.
ProxyPass rules match in order
ProxyPass /webservice/ http://internal:8080/foo-webservice/
ProxyPassReverse /webservice/ http://internal:8080/foo-webservice/
ProxyPass /website/ http://internal:8080/foo-website/
ProxyPassReverse /website/ http://internal:8080/foo-website/
ProxyPass / http://internal:8080/foo-website/
ProxyPassReverse / http://internal:8080/foo-website/
No rewrite rule. Isn't that good enough ?
I think that you need to use the first attempt but include the QSA (query string append) flag in the square brackets at the end of each RewriteRule directive.
I think the issue with Attempt 2 (none of the files in the js, img or css folders being mapped) was a sign that my approach was wrong.
My solution now is to redirect any requests to the root, to the foo-website webapp.
<VirtualHost *:80>
ServerName foo.domain.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ErrorLog /var/log/apache2/foo_error.log
LogLevel warn
CustomLog /var/log/apache2/foo_access.log combined
# RewriteRules
RewriteEngine On
RewriteRule ^/$ /foo-website/ [R]
# ProxyPass
ProxyPreserveHost On
ProxyPass / http://internal:8080/
ProxyPassReverse / http://internal:8080/
</VirtualHost>
This was not what I originally wanted, but I think this is the resolution.