Reverse Proxy backend having Path

Hi,

I am trying to implement following the rule for my subdomain:
sogo.example.com -> 127.0.0.1:52180/SOGo/

According to the documentation should be fairly easy, just add AddPrefix to the rule in configuration. The page will load but it is without styles and scripts, so it works just for the main html file.. for all the remaining content I am getting 403: Forbidden.

Will appreciate any input here. Thanks, Michal

Config:

[backends.mailcow]
  [backends.mailcow.servers.1]
    url = "http://127.0.0.1:52180"
    weight = 1

[frontends.sogo]
  backend = "mailcow"
  entryPoints = ["http", "https"]
  passHostHeader = true
[frontends.sogo.headers]
  forceSTSHeader = true
  STSSeconds = 315360000
  STSIncludeSubdomains=true
  STSPreload = true
  [frontends.sogo.routes.1]
    rule = "Host:sogo.example.com;AddPrefix:/SOGo"

Result:

Hi @MacGyver27, thanks for this detailed and clear input!

As the screenshot shows, the configuration you've done is working well: the first request is in HTTP/200, and answered HTML code, which means the request was forwarded correctly to the backend application successfully.

Now you're facing a 2nd challenge: the HTML code reference ressources (CSS for instance) without being aware of the URL rewriting done at Traefik level.
In the example here, the CSS URL is handled by Traefik in the exact same way as the frontend rule defines:

https://sogo.example.com/SOGo.woa/WebServerResources/css/theme-default.css is changed by Traefik to http://127.0.0.1:52180/SOGo/SOGo.woa/WebServerResources/css/theme-default.css .

The request to your backend server on the path /SOGo/SOGo.woa/WebServerResources/css/theme-default.css answers HTTP/403 which is then forwarded by Traefik.

Here are a few questions to be able to guide you to the right answer:

  • Is this path expected to be ok? Or should it be something else (like http://127.0.0.1:52180/SOGo.woa/WebServerResources/css/theme-default.css without the /SOGo/ prefix?)
  • Is the backend application application SOGO has a configuration directive to define the "external url"?
  • Can you share here an excerpt of the HTML code referencing the CSS resource? I want to see the link generated (is it absolute with the domain name? is it relative with or without a slash at the beginning?)

Thanks for fast reply!

Was comparing it directly on the backed and It should be without the /SOGo/ prefix:

No. SOGo wasnt altered in any way for this particular subdomain. It is part of mailcow dockerized stack. So mainly is accessible via mail.example.com/SOGo/ but I wanted here a separate subdomain just for the email client.

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title sg-default="SOGo Groupware">SOGo Groupware</title>
        <meta name="hideFrame" content="0" />
        <meta name="description" content="SOGo Web Interface" />
        <meta name="author" content="Inverse inc." />
        <meta name="robots" content="stop" />
        <meta name="build" content="@shiva2.inverse 201903020208" />
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1" />
        <link rev="made" href="mailto:support@inverse.ca" />
        <link href="/SOGo.woa/WebServerResources/img/sogo.ico?lm=1551559708" rel="shortcut icon" type="image/x-icon" />
          <link href="/SOGo.woa/WebServerResources/css/theme-default.css" rel="stylesheet" type="text/css" />
        <link href="/SOGo.woa/WebServerResources/css/styles.css" rel="stylesheet" type="text/css" />

...omitted

          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/lodash.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-animate.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-sanitize.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-aria.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-cookies.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-messages.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-material.min.js"></script>
          <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/vendor/angular-ui-router.min.js"></script>
            <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/Main.js?lm=1551559708"></script>
            <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/Common.js?lm=1551559708"></script>
            <script type="text/javascript" src="/SOGo.woa/WebServerResources/js/custom-sogo.js?lm=1546011515"></script>
      </body>
    </html>

Thanks a lot! Michal

OK cool, thanks for this feedback.

It means that a second route should be created to handle these sub resources:

http://sogo.example.com/SOGo.woa/* -> 127.0.0.1:52180/SOGo.woa/*

(capturing only requests with the path prefix /SOGo.woa/ and forwarding it to the backend without adding the prefix /SOGo/.

If my understanding is correct, add this new route to the sogo frontend:

# ...
[frontends.sogo]
  backend = "mailcow"
  entryPoints = ["http", "https"]
  passHostHeader = true
[frontends.sogo.headers]
  forceSTSHeader = true
  STSSeconds = 315360000
  STSIncludeSubdomains=true
  STSPreload = true
  [frontends.sogo.routes.mainPage]
    rule = "Host:sogo.example.com;AddPrefix:/SOGo"
  [frontends.sogo.routes.subResources]
    rule = "Host:sogo.example.com;PathPrefix:/SOGo.woa"

let us know the result?

Thanks for the suggestion.

Result is that is not even loading the main page:
404 page not found for either:

  [frontends.sogo.routes.mainPage]
    rule = "Host:sogo.example.com;AddPrefix:/SOGo"
  [frontends.sogo.routes.subResources]
    rule = "Host:sogo.example.com;PathPrefix:/SOGo.woa"

or

  [frontends.sogo.routes.mainPage]
    rule = "Host:sogo.example.com;AddPrefix:/SOGo"
  [frontends.sogo.routes.subResources]
    rule = "PathPrefix:/SOGo.woa"

I am sorry, I gave you a wrong configuration, as pointed out by my fellow @ldez (thanks!).

In fact, the syntax I gave you make a logical AND between the 2 rules (I thought creating 2 different routing rules with different names would be a logical OR).

=> The solution is to create another frontend with the 2nd rule.

Its raining 200's!!!!!!!!!! :partying_face:

Thank you for the attention.

BTW: only way to perform OR is to have 2 completely separate frontends? Thx

1 Like

Yes, with Traefik v1. You might want to look at Traefik v2, which provides improved features :slight_smile:

Two more questions here:

1 - Just to clarify I understood correctly. Problem was that static resources were not under /SOGo segment thus we would need just a separate rule like this: rule = "Host:sogo.aronmgv.com but that does not work.. So it needs to be combined with something else. Then I read about the PathPrefix "(if your backend listens on a particular base path but also serves requests on sub-paths)" But still doesnt understand its necessity

2- What would happen if we would merge them into single frontend rule then (also an AND?).. Host:sogo.example.com;AddPrefix:/SOGo;PathPrefix:/SOGo.woa?

Hi @MacGyver27, about the 2 questions:

1 - My understanding is that the backend application serves 2 different contexts:

  • The index.html page is served under http://127.0.0.1:52180/SOGo/*
  • The static resources are served under http://127.0.0.1:52180/SOGo.woa/*.
    So this translates to 2 routings rules: one per backend context.
    You did the first rule correctly (catching incoming requests on the root context / and adding the prefix. But you add to implement the 2nd rule (catching incoming requests to /SOGo.woa and forwarding without adding the prefix /SOGo/.). PathPrefix is used in this 2nd rule to only catche requests on the path prefix /SOGo.woa/*: the rest should be treated by the first request.

2 - If you merge both, then the prefix is ALWAYS added, which is not working on the backend (it serves requests under /SOGo.woa/*, and not under /SOGo/SOG.woa/*.

1 Like

Hello again. I am facing very similar problem but cannot succeed with the proper reverse proxy configuration.

Scenario is now that I have an Spring Boot App with Angular on the frontend. I have built a Docker image of this app.

How it looks locally:

opening in browser:
http://192.168.255.11:59901/spring/webapp (no trailing slash)
will redirect to:
http://192.168.255.11:59901/spring/webapp/login?returnUrl=%2F
giving you the app (with all resources like js|css|owa|etc.. loaded):

However when I try to put it behind subdomain I am not able to succeed. I wanted to achieve this 2 scenarios:
a) alias_for_client.example.com (addPrefix: /spring/webapp) - access only to angular context
b) alias_for_admin.example.com/webapp (addPrefix: /spring) - access to admin tools of spring boot (/spring/swagger, /spring/explorer, /spring/h2-database, /spring/acucator, etc.)

Non of them will allow me to load resources like css, js and others.. I am getting 403:

Simply put I want to have http://192.168.255.11:59901 put under subdomain and strip the path segment (or add it in the background) as described above.

If somebody can point me what I might be doing wrong please. Thanks!