Score:0

nginx reverse proxy with subpath

in flag

I built a web app that will listen on a port and handle HTTP requests. For example, if I run it locally at 127.0.0.1:3000. I can access it with http://127.0.0.1:3000/path/within/app on my browser. I would like to deploy it on one of my servers, which is configured with nginx to handle all incoming requests (and TLS) and forward them to different applications (listening at http://127.0.0.1:xxx). Normally, I would give each app a different subdomain (e.g., access app1 with app1.example.com and app2 with app2.example.com), but it would be more convenient if I can use subpath (e.g., access app1 with example.com/app1 and app2 with example.com/app2). But I am not sure how to configure it.

My current configuration file is like the following. Suppose my app is listening at 127.0.0.1:3000.

location ^~ /app1 {
    proxy_set_header    X-Real-IP  $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header    Host $http_host;
    proxy_redirect      off;
    proxy_pass          http://127.0.0.1:3000/;
}

I would like to achieve the following.

  1. When I access https://example.com/app1, it will be equivalent to accessing http://127.0.0.1:3000.
  2. When I access https://example.com/app1/path/within/app, it will be equivalent to access http://127.0.0.1:3000/path/within/app.

However, with the above mentioned configuration file, only the first part work. If I access https://example.com/app1/path, my app complaints that it was http://127.0.0.1:3000//path that actually get accessed, and it doesn't know how to handle //path.

I would prefer not to modify any part of my application so that it can run independently if I decided to give it a subdomain in the future, and expects a fix with only modifying the nginx configuration file if possible. In addition, I am aware of the problem that any clickable links generated by the app will also need to handle subpath, but this app is simple enough that that is not a problem.

Thanks.

Ivan Shatsky avatar
gr flag
Change your location to `location ^~ /app1/ { ... }` (note the trailing slash). If you want the `/app1` URI to be workable too, add `location = /app1 { return 301 /app1/; }` to your configuration.
lewisxy avatar
in flag
Thanks, are there ways to make `/app1` work without sending 301?
Ivan Shatsky avatar
gr flag
You can try `location = /app1 { rewrite ^ /app1/ last; }`. However in some cases it can make your app unable to load its assets (see the explanations in [this](https://stackoverflow.com/a/70778444/7121513) answer) and I don't recommend to do it.
Score:0
us flag

Try the following configuration

location /app1/ {
    proxy_set_header    X-Real-IP  $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header    Host $http_host;
    proxy_redirect      off;
    proxy_pass          http://127.0.0.1:3000/;
}

location /app1 {
    return 301 /app1/;
}
lewisxy avatar
in flag
Thanks, it works. However, are there ways to configure it so that I don't need to send 301 when client accesses `/app1`? In other words, I would prefer redirect on server side rather than client side, if possible.
us flag
Are you sure that is what you want? Then you will have duplicate content at `http://example.com/app1` and `http://example.com/app1/` URLs, which is a problem for SEO.
lewisxy avatar
in flag
The current app I am working on only provide JSON APIs, so no HTML page. However, I don't have enough experience on this topic. What is the convention if my app is an actual website? Do we generally prefer the one with trailing slashes or not? Also, how does this choice affect query parameters (those after `?`), if at all?
us flag
Query arguments are independent of the path component of a URL, so there it doesn't matter. In my own projects, I do 301 redirect from `/app1` to `/app1/`, because the one with ending slash is easier to handle in different places.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.