Apache proxy different context path cookie issue - apache

I'm currently developing an application that will be deployed in a Docker container. The Docker contains a Tomcat that runs the application as ROOT.war, so at top level.
The idea is that when our users run the container, they may want to run several copies on a specific context path on their servers each, so for example:
https://somedomain.com/a and https://somedomain.com/b
My plan was to simply tell them to configure a proxy reverse like this:
ProxyPreserveHost On
RewriteEngine On
# Map https://somedomain/a to http://internalserver:9001
RewriteRule ^/a$ /a/ [R]
ProxyPass /a/ http://internalserver:9001/
ProxyPassReverse /a/ http://internalserver:9001/
# Map https://somedomain/b to http://internalserver:9002
RewriteRule ^/b$ /b/ [R]
ProxyPass /b/ http://internalserver:9002/
ProxyPassReverse /b/ http://internalserver:9002/
Where 9001 and 9002 are the ports of the two Docker containers running copies of my application.
Now, this makes the application run, but there are issues with cookies, as the context path on the server in Tomcat is always empty and therefore there are session issues.
I've seen several questions about similar situations, but in all cases, people are able to either change the public path or the path within Tomcat to make them match. In my case, I simply cannot do that, because I'd be dictating which path the users of our software would have to use.
Here are examples of such questions:
https://serverfault.com/questions/311994/how-to-proxy-context-to-different-backend-context-in-apache
https://serverfault.com/questions/495017/how-do-i-ensure-the-context-path-is-the-same-when-accessing-a-web-app-via-apache
Tomcat behind an apache proxy error on path
Is there any way to make this setup work properly?
Can I change the proxy configuration to forward the context path somehow?
Are there other options?

Ok, I found a quite simple solution. Maybe it'll help someone else, so I'll post it here:
I figured out that there's a proxy config option called ProxyPassReverseCookiePath which is meant to be used for exactly what I was trying to achieve, so I changed the config to this:
RewriteRule ^/a$ /a/ [R]
<Location /a/>
ProxyPass http://internalserver:9001/
ProxyPassReverse http://internalserver:9001/
ProxyPassReverseCookiePath / /a
</Location>
RewriteRule ^/b$ /b/ [R]
<Location /b/>
ProxyPass http://internalserver:9002/
ProxyPassReverse http://internalserver:9002/
ProxyPassReverseCookiePath / /b
</Location>
This maps every cookie path coming from the internal server with a path of / to /a or /b depending on the application, which is exactly what I wanted. The application itself now always sets the cookie path to just / if there is no context path available. The reverse proxy then maps it back to wherever it was requested from.

Related

How to server static files + proxy context

I am wondering how to configure my httpd server to serves the following pages:
My need is to serve static content located in my /var/www/static when url is /context/static and to proxy the remaining to a tomcat server
In this order:
/context/static/* --> files served by httpd
/context/* --> resources served by tomcat
I have tried to rewrite /context/static/* to a folder pointing to my /var/www/static and added the ProxyPath directive for the remaining but I can't get it working.
What are the best practices and how to achieve that ?
Thanks in advance
Well, in fact it is quiet easy...
Having such folders configured:
/var/www/static/
|- css/*
|- js/*
\ medias/*
The following httpd configuration will redirect static/* to the /var/www and the rest will be proxied
# first rewrite for statics
RewriteEngine On
RewriteRule ^/context/static/(.+)$ /static/$1
# then proxy remaining...
ProxyPass /context http://127.0.0.1:8080/context
ProxyPassReverse /context http://127.0.0.1:8080/context
I've found the following approach that works and is quite general. (4/12/2018)
Location/Proxypass expressions always take priority over any other location block, so you have to Exclude the paths that you don't want to be proxied. the "?!" does that in the regex. Since static content is, um, static, it is not so bad to require that the apache configuration be updated if another directory is needed to be served directly for a different media type.
The following was taken from a server that was proxying a Python Flask application.
<LocationMatch "^/(?!js|css|media)" >
ProxyPass http://127.0.0.1:5000
ProxyPassReverse http://127.0.0.1:5000
</LocationMatch>
<Location "/">
Require all granted
</Location>
Both of the existing answers rely on Regular Expressions. While they work, it is possible to do this without such complicated constructs. ProxyPass can take "!" as a second parameter, in which case it doesn't proxy the matching URL. For example
ProxyPass /context/static/ !
ProxyPass /context http://127.0.0.1:8080/context
ProxyPassReverse /context http://127.0.0.1:8080/context
or, with multiple exclusions,
ProxyPass /js !
ProxyPass /css !
ProxyPass /media !
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
These exceptions need to come before the more general rule in order to take precedence.
Thanks to freenode user "thumbs" in #httpd.

Apache ProxyPass to 2 different tomcat servers with same URI

I have 2 servers with apache http server (2.4.9) on them. I have 2 servers with tomcat 7.0.39 running on them. Ultimately I need to load balance between the 2, but right now am simply trying to get this ProxyPass configuration to work.
I have one url on the 2 apache servers- example.com. They are load balanced. The load balancing is in place and there is no issue.
I have 2 applications, 1 on each tomcat server. Each tomcat server has 2 instances of tomcat running- each on a different port. They are running a very similar application with the exact same uri.
I need to redirect:
example.com/site1 to example.com/app (for app1)
example.com/site2 to example.com/app (for app2)
I can redirect this easily enough for 1 application only:
ProxyPass /app/ AppSrv:8080/app/
ProxyPassReverse /app/ http://example.com/app/
I can get to the page, log in, no problem. For a singe application only.
When I set up a configuration for both applications, I can get to the login page of both applications as well when configured as such:
ProxyPass /site1/ AppSrv:8080/app
ProxyPassReserve /app/
ProxyPass /site2/ AppSrv:8081/app
ProxyPassReverse /app/
Both urls come up with the tomcat application login page. But neither work after this- they fail. The uri reads 'site1' (or 'site2') not 'app'. I cannot log in.
The application requires the uri '/app/' as the base uri in order to function.
The applications are listening on different ports, but have the same uri. How do I keep the uri in the url, but change it so the application responds?
Ultimately I have to balance this, but I've done that before. This is the part I'm having a hard time with.
Ok, I finally solved this. I had to modify the header.
ProxyPass /site1/ balancer://example.com/app/
ProxyPass /site2/ balancer://example.com/app/
<Location /site1>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site1
Header edit Location ^(https?://)?example.com/app/ /site1/
</Location>
<Location /site2>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site2
Header edit Location ^(https?://)?example.com/app/ /site2/
</Location>

How to run PrimeFaces behind reverse proxy in a subdomain?

I have build an application with PrimeFaces and want to run that behind an apache reverse proxy.
My target url looks like this http://myserverurl.org:8080/myapplication/.
I want to access the application via subdomain like this http://myapplication.myserverurl.org.
I have configured a VirtualHost in apache:
<VirtualHost *:80>
ServerName myapplication.myserverurl.org
ProxyPass / http://myserverurl.org:8080/myapplication/
ProxyPassReverse / http://myserverurl.org:8080/myapplication/
</VirtualHost>
That works not so well. I can see the JSF page, but there is no CSS applied etc. I can see that the first request is redirected correctly, but the following requests (to load jQuery, CSS, etc.) are not.
They try to access an url like http://myapplication.myserverurl.org/myapplication/faces/javax.faces.resource/primefaces.js?ln=primefaces which is obviously wrong. They must not include the /myapplication/ path again, since the proxy redirects already to that path.
How can I solve this issue? Is this a PrimeFaces problem or a problem with my reverse proxy configuration?
Using (or not using) AJP has no bearing on resolving this specific issue.
Primefaces internally uses context path variable to include CSS and Javascript resources. Even using AJP you will end up with:
/unwantedAppContext/javax.faces.resource/jquery/jquery.js.jsf?ln=primefaces
What you could do to resolve this add another proxy pass to handle the unwanted context. This may not be the best solution, but it works.
<VirtualHost *:80>
ServerName myapplication.myserverurl.org
ProxyPass /myapplication/ http://myserverurl.org:8080/myapplication/
ProxyPassReverse /myapplication/ http://myserverurl.org:8080/myapplication/
ProxyPass / http://myserverurl.org:8080/myapplication/
ProxyPassReverse / http://myserverurl.org:8080/myapplication/
</VirtualHost>
The order of the pass matters.
This issue was also reported in the icefaces forum
http://www.icesoft.org/JForum/posts/list/4433.page#sthash.h1qSqiYg.dpbs
It may be different depending on the application server but, as a main rule, you should use AJP for the proxying.
First step is to enable ajp modules depending on OS. Ubuntu looks like this.
sudo a2enmod proxy proxy_ajp
Step 2, change the proxy definition in the apache conf to something like:
ProxyPass / ajp://localhost:8009/myapplication
ProxyPassReverse / ajp://localhost:8009/myapplication
Step 3 is to enable it on the application server. Again, it varies depending of the one you use. Tomcat has a commented out section in the server.xml. Glassfish has a check-box in the admin console and an asadmin command (but I can't remember it)
Consider using ProxyHTMLURLMap directive from mod_proxy_html module. This module manipulates output HTML links to be pointed to the right location. In your case all the links that tell http://myapplication.myserverurl.org/ need to be changed back to /, i.e.
ProxyHTMLURLMap http://myapplication.myserverurl.org/ /
This way you can modify any call-back links that are pointing to wrong location.
Answer of jjhavokk works but
for Graphics you need to reference them via request.contextPath
<img src="#{request.contextPath}/resources/yourfolder/yourpng.png" />
Place it in webapp/resources/yourfolder/yourpng.png
With my .css file this was not needed
h:outputStylesheet name="css/screen.css"
in webapp/resources/css

How to rewrite / proxy an Apache URI to an application listening on a specific port / server?

They say that Apache's mod_rewrite is the swiss-army knife of URL manipulation, but can it do this?
Lets say I want to add a new application to my Apache webserver, where the only configurable option of the app is a port number.
I want to use & give out URLs of the form "http://hostname.example.com/app" rather than "http://hostname.example.com:8080". This would ensure that clients would be getting through the institution's firewall as well, and it's generally tidier.
My application includes absolute URIs in php, javascript and css, so I want to prepend my own root location to the URI in the applications internal links. I have no access to DNS records and so can't create another name-based virtual server.
Using Apache's mod_rewrite and mod_proxy modules, I can transparently redirect a client to the correct home-page of the application. But links within that homepage don't point a client to links relative to the new base URL.
So, what's the best way of proxying a request to an application that is listening on a specific port?
For example, if I had an application listening on port 8080, I could put this in my Apache configuration:-
<VirtualHost *:80>
SSLProxyEngine On
ServerName myhost.example.com
RewriteEngine On
UseCanonicalName On
ProxyVia On
<Location "/application">
RewriteRule ^/application/?(.*) http://localhost:8080/$1 [P,L]
</Location>
</VirtualHost>
This would work fine if the application didn't use absolute URLs, but it does. What I need to do is rewrite URLs that are returned by the application's css, javascript and php.
I've looked at the ProxyPass and ReverseProxyPass documentation, but I don't think these would work..?
I've also come across Nick Kew's mod_proxy_html, but this isn't included in the standard Apache Distribution, and my institution's webserver seems to have been fine for years without it.. Other than trawling manually (or using a grep -r | sed type expression) through the application's source code, or using this 3rd party add-on, are there any other ways to go about this?
Could I perhaps use some of the internal server variables in a mod_rewrite rule? For example a rewrite rule based on ’HTTP_REFERER'?
Using mod_proxy would work just fine. For instance, I mapped https://localhost/yalla/ to point to a subdirectory of my webserver:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost
</Proxy>
ProxyPass /yalla/ http://yalla.ynfonatic.de/tmp/
If you implement this, you'll note that the pictues of the directory-listing aren't visible; this is because they're below the /tmp/ directory on the remote server, hence not visible.
So, in your case you'd do:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost # Or whatever your network is if you need an ACL
</Proxy>
ProxyPass /app/ http://hostname.example.com:8080/
Like with everything in Apache configuration, watch those trailing slashes when referring to directories.
Good luck!
Alex.

Stuck with apache,mod-ajp weird redirection

hi all i have a redirection problem with mod ajp, that it always adds the application name before the desired page, for example:
if i requested the page:
http://myapp.com/mypage
it is converted to
http://myapp.com/myapp/mypage, and i get a 404 error
i don't know why such behaviour occurs, this is the configuration:
<Proxy *> AddDefaultCharset Off Order deny,allow Allow from all </Proxy>
ProxyPass / ajp://127.0.0.1:8009/myapp/
ProxyPassReverse /
ajp://127.0.0.1:8009/myapp/
ProxyPassReverseCookiePath /myapp/
this strange redirection occurs exaclty when an inside application redirection occurs meaning after registration the user is redirected(application side) to the login page using response.sendRedirect , any ideas ?
The ProxyPassReverse directive is possibly wrong. I guess it should be
ProxyPassReverse / http://myapp.com
See The Mystery of ProxyPassReverse.
You can resolve problems like this with this approach:
Install LiveHTTPHeaders and enable it
Access the application directly
Access the application via your reverse proxy
Compare the HTTP traffic of the previous cases
Most likely your application redirects user using relative URL. However your ProxyPassReverse only rewrites absolute versions. The relative version gets redirected with the page load according to your ProxyPass rule, causing the doubling of the path.