Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thymeleaf template (in Spring boot application) behind reverse proxy not forming url's correctly

I have some trouble getting Thymeleaf to form relative URL's correctly when it is used on a server behind a reverse proxy (nginx in my case).

Let's say I have the following location in nginx:

location /app {
    proxy_pass http://10.0.0.0:8080;
}

I have the following Thymeleaf 3 page (index.html):

<html xmlns:th="http://www.thymeleaf.org">

<head>
    <link rel="stylesheet" th:href="@{/css/some.css}" />
</head>
<body>
    Hello world!
</body>
</html>

The server used is an embedded Tomcat server (Spring boot), running at context /.

When I send a request to http://example.com/app, then I get the index.html page as response. The css cannot be retrieved however, because when the URL is constructed in the Thymleaf template, it uses the context path of the tomcat server, which is /. The constructed url in the index.html looks as follows:

http://example.com/css/some.css

This obviously results in a 404 not found. The URL needs to be formed as follows:

http://example.com/app/css/some.css

What do I need to configure to let Thymeleaf form the URL as http://example.com/app/css/some.css? I would rather not hardcode the base URL anywhere for certain profiles or something like that. I think I need to add something to the nginx configuration, but I'm not sure what exactly.

like image 619
n1ck Avatar asked May 17 '17 10:05

n1ck


2 Answers

Correct solution is to inform springboot application that it is being behind proxy.

Try to extend nginx config to something like this:

location /app {
    proxy_pass http://10.0.0.0:8080;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Prefix /app;
}

To learn about using Forwarded header (standard for a few years), have a look at https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/ There are a bit mismatch in spring documentation for this topic and you can have a look at some issues/project to gain more info:

  • "plugin" which helps a lot https://github.com/qaware/x-forwarded-filter
  • https://github.com/spring-projects/spring-boot/issues/15046
  • https://github.com/spring-projects/spring-hateoas/issues/862
  • https://github.com/spring-projects/spring-security/issues/7081

PS: If you are testing your springboot app configuration, it can come handy to do it locally with cURL, without need to use nginx. To simulate request headers like comming from proxy, you can use this command:

curl -i http://localhost:8080 \
    -H 'X-Forwarded-Host: example.com' \
    -H 'X-Forwarded-Port: 443' \
    -H 'X-Forwarded-prefix: /myDevelApp' \
    -H 'X-Forwarded-proto: https'

Or using standardized header:

curl -i http://localhost:8080 \
    -H 'X-Forwarded-prefix: /myDevelApp' \
    -H 'Forwarded: for=123.333.333.333;host=example.com;proto=https'
like image 67
Lubo Avatar answered Sep 20 '22 18:09

Lubo


Ended up matching the context of the Tomcat server to the desired Nginx location. According to above example, the context would be set to '/app'.

Edit: I set the application context property in the application.yml:

server:
  servlet:
    contextPath: /app
like image 34
n1ck Avatar answered Sep 17 '22 18:09

n1ck