2

so I have a bit of a problem with how urls are generated inside my web app.

I have my 'demo' springboot app deployed on my server as 'demo.war' (which expodes to a 'demo' folder). I also have an apache subdomain configured to map demo.myserver.com to the correct context on tomcat:

<VirtualHost *:80>
  ServerAdmin admin@myserver.com
  ServerName demo.myserver.com

  ProxyRequests Off
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>
  ProxyPass / ajp://localhost:8009/demo/
  ProxyPassReverse / ajp://localhost:8009/demo/
</VirtualHost>

so far so good. When I go to the http://demo.myserver.com it will pass to the 'demo' context in the tomcat and the page loads. The problem is in how the context-relative URLs in the page are created. The final relevant generated HTML looks like this:

<form action="/demo/loadDataSet" method="get">
  <button type="submit">Load next dataset</button>
</form>

The thymeleaf template bit looks like this:

<form th:action="@{/loadDataSet}" method="get">
  <button type="submit">Load next data set</button>
</form>

Once I click on such button the URL used is http://demo.myserver.com/demo/loadDataSet which fails with 404 because there is no mapping for the 'demo' context in my 'demo' subdomain. What I would like to know is what to do to generate the html so it looks like this:

<form action="/loadDataSet" method="get">
  <button type="submit">Load next dataset</button>
</form>

Thanks guys

Tomas Babic
  • 269
  • 5
  • 14

2 Answers2

1

So I had to look into it a bit deeper myself. As it turned out Thymeleafs are not responsible for the problem in first place. It was my apache configuration issue (should I change the title of the question now?) after all.

Here is the configuration for the apache I came up with:

<VirtualHost *:80>
  ServerAdmin admin@myserver.com
  ServerName demo.myserver.com

  ProxyRequests Off
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>    
  ProxyPreserveHost On
  <Location />
    ProxyPass ajp://localhost:8009/demo/
    ProxyPassReverse ajp://localhost:8009/demo/
    SetOutputFilter INFLATE;proxy-html;DEFLATE
    ProxyHTMLURLMap /demo/ /
    ProxyPassReverseCookiePath /demo/ /
  </Location>
</VirtualHost>

The key here was the line with ProxyHTMLURLMap which takes all references of /demo/ in the HTML passed through and replaces it with /. The ProxyHTMLURLMap can only be withing the <Location> tag where the / is not marking closing of the tag but the path/context to map. In my case the root in the demo subdomain.

Also there was a problem with the configuration of the proxy_html module. For whatever reason the proxy_html.conf was missing so I had to create it myself and to add this inside:

# Here's the declaration for W3C HTML 4.01 and XHTML 1.0
ProxyHTMLLinks  a       href
ProxyHTMLLinks  area        href
ProxyHTMLLinks  link        href
ProxyHTMLLinks  img     src longdesc usemap
ProxyHTMLLinks  object      classid codebase data usemap
ProxyHTMLLinks  q       cite
ProxyHTMLLinks  blockquote  cite
ProxyHTMLLinks  ins     cite
ProxyHTMLLinks  del     cite
ProxyHTMLLinks  form        action
ProxyHTMLLinks  input       src usemap
ProxyHTMLLinks  head        profile
ProxyHTMLLinks  base        href
ProxyHTMLLinks  script      src for
# To support scripting events (with ProxyHTMLExtended On),
# you'll need to declare them too.
ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
    onmouseover onmousemove onmouseout onkeypress \
    onkeydown onkeyup onfocus onblur onload \
    onunload onsubmit onreset onselect onchange

I have used samples from here, here and here while I was trying the solution out. Hope it helps to someone else as well.

Community
  • 1
  • 1
Tomas Babic
  • 269
  • 5
  • 14
0

Have you tried adding

ProxyPreserveHost On

I'm not really familiar with but that seems to be recommended in questions like this:

Why does getContextPath() under a proxy return the internal path inside HttpServlet but not inside Filter?

The other option would be something like this:

<form action="@{~/loadDataSet}" method="get">
  <button type="submit">Load next dataset</button>
</form>

Which is a server relative url.

Community
  • 1
  • 1
Metroids
  • 18,999
  • 4
  • 41
  • 52
  • Hi @Metroids, thanks for a tip but that would not help. The ProxyPreserveHost is only for passing the url in headers. Also the second suggestion to use the server relative context is asking for a trouble in case there are multiple apps deployed on the server. But thanks – Tomas Babic Oct 03 '16 at 10:06