0

I have multiple single page applications running each in their own container under the home directoy which is quite straight forward.

Now I would like to route to those applications under the same dns entry using different paths, e.g.:

domain.com      -> defaultAppContainer
domain.com/app1 -> container1
domain.com/app2 -> container2

I do not have the option to rewrite the paths during routing, so I would like for Nginx to listen to the path /app1 or /app2 respectively and serve the applications correctly from there. Currently everything I have tried results in an error.

I have considered two possibilities:

  • Proxying the sub path to home using something like
    location /app1 {
      proxy_pass $host/;
    }
    
    But this does not seem to work for the frontend, I assume some paths are messed up in the request.
  • Serving all files under the sub route, e.g.:
    location /app1 {
      alias root /usr/share/nginx/html/;
    }
    
    Where the alias points to the base dir of the built web app. This gives me a CONN_RESET error.

Also simply redirecting with a 307 is not an option as that would lead to the client calling the base url without the path, which is then routed to the default app.

masus04
  • 121
  • 2
  • 6

2 Answers2

4

Generally running the app under an URI prefix when the app itself does not expect it is a tricky thing, and the only reliable solution would be to fix/setup the app making it generate all the assets/routes links either relative or including the prefix it is deployed under. Almost every existing workarounds are to rewrite the application responses "on-the-fly" replacing generated links with the new ones. Some kind of a generic answer is here, some additional considerations can be found here.

However if it is a really SPA, lets say a React app that uses something like HashRouter rather than BrowserRouter, a workaround based on the conditional rewrite according to the request Referer HTTP header is possible:

server {
    ...
    if ($http_referer ~ ^https?://yourdomain.com/app1/) {
        rewrite ^ /app1$uri;
    }
    if ($http_referer ~ ^https?://yourdomain.com/app2/) {
        rewrite ^ /app2$uri;
    }
    ...
    location /app1/ {
        proxy_pass http://container1/;
    }
    location /app2/ {
        proxy_pass http://container2/;
    }
}

All the trailing slashes used here are used on purpose, removing any of them will break the solution!

This is not applicable for anything else than SPA (including applications that are using "virtual" routing based on the HTML5 browser history API) since the rewrite logic will be broken after the very first page-to-page transition.

Ivan Shatsky
  • 2,726
  • 2
  • 7
  • 19
  • Thanks a lot for your reply! All Applications are implemented using one of the following: react, vuejs or Flutter, but this is where the guarantees end and I don't have control over the exact implementations. Also, what is the exact function of the rewrites? – masus04 May 17 '22 at 22:24
0

Here there is an example how you can deploy multiple angular/react/vue.js apps and an API to separate path and serve them through Nginx:

server{
        server_name yourdomain.com;

        location /api{
                proxy_pass          http://127.0.0.1:8080;
                proxy_http_version  1.1;
                proxy_set_header    Upgrade             $http_upgrade;
                proxy_set_header    Host                $host;
                proxy_set_header    X-Real-IP           $remote_addr;
                proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    location /admin {
                alias /data/app/ui/admin;
                index index.html index.htm;
                try_files $uri $uri/ /admin/index.html;
                }
    location /client {
                alias /data/app/ui/client;
                index index.html index.htm;
                try_files $uri $uri/ /client/index.html;
                }
    location /business {
                alias /data/app/ui/business;
                index index.html index.htm;
                try_files $uri $uri/ /business/index.html;
                }
    location / {
                alias /data/app/ui/common/;
                index index.html index.htm;
                try_files $uri $uri/ /index.html =404;
                }
}

Reference to the orginal solution can be found under following link: reference link

b4hkid
  • 1
  • 2
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/543691) – RalfFriedl Mar 05 '23 at 00:35