5

Currently, I am able to visit: https://files.mydomain.com/files. Even if I go to https://files.mydomain.com, it will redirect automatically to https://files.mydomain.com/files successfully.

Instead, I would like for NGINX to automatically rewrite https://files.mydomain.com/files -> https://files.mydomain.com

My current NGINX code:

http {

    server {
        
            listen       80;
            server_name  localhost;
            return 301 https://$host$request_uri;
    }

    server {

            listen       80;
            server_name  files.mydomain.com;
            location / {
                return 301 https://files.mydomain.com$request_uri;
        }
    }

    server {
            listen 443 ssl http2; 
            listen [::]:443 ssl http2;
            server_name  files.mydomain.com;
            client_max_body_size 0;
            location / {
                return 301 https://$host/files;
            } 
            location /files {
                proxy_pass http://localhost:89;
            }
    }

    #Root Domain
    server {
            listen 443 ssl http2; 
            listen [::]:443 ssl http2;
            server_name_in_redirect off;
            server_name  www.mydomain.com mydomain.com;
            log_not_found off;

        location / {
            root   /inetpub/wwwroot;
            index  index.html index.htm;
        }
    }
}

My best attempt:
Unfortunately, it just takes me to the "Welcome to NGINX" webpage when I visit: https://files.mydomain.com

http {

    server {
        
            listen       80;
            server_name  localhost;
            return 301 https://$host$request_uri;
    }

    server {

            listen       80;
            server_name  files.mydomain.com;
            location / {
                return 301 https://files.mydomain.com$request_uri;
        }
    }

    server {
            listen 443 ssl http2; 
            listen [::]:443 ssl http2;
            server_name  files.mydomain.com;
            client_max_body_size 0;
            location ^~ /files {
                rewrite ^/files/?(.*)$ https://files.mydomain.com/$1 permanent;
                proxy_pass http://localhost:89/files;
            }
    }

    #Root Domain
    server {
            listen 443 ssl http2; 
            listen [::]:443 ssl http2;
            server_name_in_redirect off;
            server_name  www.mydomain.com mydomain.com;
            log_not_found off;

        location / {
            root   /inetpub/wwwroot;
            index  index.html index.htm;
        }
    }
}
MKANET
  • 573
  • 6
  • 27
  • 51

2 Answers2

2

*** [Final answer] ***

After several tests, the following configuration covers almost all the prerequisites.

Both / and /files/ are forwarded to localhost:89/files/.

server {
    listen 443 ssl;
    ssl_certificate .../fullchain.pem;
    ssl_certificate_key .../privkey.pem;

    server_name files.mydomain.com;

    location /files/ { 
        proxy_pass http://localhost:89/files/;
    }       

    location / { 
        proxy_pass http://localhost:89/files/;
    }
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

In this real case, only a small issue at first visit :

When I visit https://files.mydomain.com for the first time, it automatically forwards to: https://files.mydomain.com/files/login.aspx. After I authenticate with my credentials, it automatically forwards to https://files.mydomain.com/files instead of https://files.mydomain.com. However the good news is if I stay logged in and revisit https://files.mydomain.com, it will continue to stay at: https://files.mydomain.com.

[Initial answer]

I know you are asking for url rewriting, but have you tried the proxy_pass+alias way?

My tests at home seem ok. I simply put files in a folder and use the following nginx configuration (I use port 8443 as a fake SSL port):

server {
    listen 8443;
    server_name files.ssl.localhost;
    root D:/WEB;

    location / {
        alias D:/WEB/secretfolder/files/;
        autoindex on; # or not, only to test folder listing
    }

    location /files/ { #beware the trailing slash
        proxy_pass http://files.ssl.localhost:8443/; #beware the trailing slash
    }
}

http://files.ssl.localhost:8443/files/ and http://files.ssl.localhost:8443 both point to the same directory listing:

directory listing

and we can get, for example, the contents of file.txt: file.txt contents

I hope this approach matches your goals or makes sense for anyone else.

Philippe
  • 1,134
  • 12
  • 22
  • Thanks. I'm not sure I understand what you're suggesting with your current solution. Could you change your answer so it matches MY desired URL and current proxy_pass line: proxy_pass http://localhost:89/files; I can give it a shot. – MKANET May 19 '23 at 04:35
  • @MKANET Yes I could, I'm going to. But, in your nginx blocks, no block defines a server listening on port 89. That was what I was stuck on. – Philippe May 19 '23 at 04:56
  • 1
    Thank you. Maybe I'm not understanding correctly..... `http://localhost:89/files` is an existing IIS ASP.NET application that's already listening on port 89. NGINX can't also listen on the same port too on the same machine concurrently. – MKANET May 19 '23 at 18:07
  • @MKANET, this explains that ^^ Another edit has been done. I cross fingers. – Philippe May 19 '23 at 20:46
  • your `Update 2` looks identical to what I'm already using. It only makes the URL: `https://files.mydomain.com/files`. It doesn't NOT change it to: `https://files.mydomain.com` unfortunately. I think it will need the correct NGINX rewrite code. – MKANET May 20 '23 at 00:37
  • @MKANET, thanks for your feedback. It does not **change** the url, but both `https://files.mydomain.com/files` and `https://files.mydomain.com` point to `http://localhost:89/files/`, same result for me. If your goal is to **mask** the `/files/` part, maybe `IIS` listening on port 89 should expose `/` location and route requests to `.../files/` real folder, so nginx could proxy requests to `http://localhost:89/`, IMHO. That was the goal of `UPDATE 1`. – Philippe May 20 '23 at 07:07
  • when I try to go to the path `https://files.mydomain.com` I get the error in the screenshot below. It looks like it's trying to access the resource `https://files.mydomain.com/files/files/login.aspx` probably trying to validate the login first. However, /files/files/ is not correct. https://imgur.com/Z9f86bJ – MKANET May 20 '23 at 11:38
  • @MKANET Thanks for the screenshot. So it could mean that IIS routes / requests to the right location itself. Fine! So, let's empty the caches of your navigator (because of previous hard redirections), and try the **`UPDATE 3`**. – Philippe May 20 '23 at 12:09
  • Phillipe unfortunately, with UPDATE3, when I go to the URL: `https//files.mydomain.com` or `https//files.mydomain.com/files` it goes to the root of my IIS website: `https//mydomain.com`...same as `http//localhost:89` _(if accessed locally on the server)_. Ultimately, `https//files.mydomain.com` or `https//files.mydomain.com/files` should be the same as `http//localhost:89/files`, not `http//localhost:89`. Sorry, StackOverflow wouldn't let me use `:` character in the URLs for this comment. – MKANET May 20 '23 at 20:14
  • @MKANET, this is what I understood when writing UPDATE 3. If you need to proxy to `http://localhost:89/files/` **UPDATE 2** should work. Would you try again the configuration in **UPDATE 2**? – Philippe May 21 '23 at 06:26
  • Philippe, **UPDATE 2** is almost PERFECT! Just a small issue. When I visit `https://files.mydomain.com` **for the first time**, it automatically forwards to: `https://files.mydomain.com/files/login.aspx`. After I authenticate with my credentials, it automatically forwards to `https://files.mydomain.com/files` instead of `https://files.mydomain.com`. **_However_** the good news is if I stay logged in and revisit `https://files.mydomain.com`, it will continue to stay at: `https://files.mydomain.com`. Can you think of a way to fix the small issue immediately after authenticating? – MKANET May 21 '23 at 21:03
  • Good morning @MKANET ;) Please, would you test **UPDATE 4**? – Philippe May 22 '23 at 08:55
  • Bonjour Philippe! I think you have a typo in your **UPDATE 4**. Specifically in this line: `return 302 https://files.mydomain.com.fr$1;`. I tried changing it to `return 302 https://files.mydomain.com/$1;` However, I am getting an error with that rewrite code. This is what I do: First, I go to: `https://files.mydomain.com` Then, I am presented with the login screen at: `https://files.mydomain.com/login.aspx`. When I enter my username/password, my browser immediately returns the following error: `files.mydomain.com says HTTP Error: 200- (Response content-type in not application/json)` – MKANET May 22 '23 at 20:19
  • @MKANET, sorry for the trailing .fr (find and replace issue ^^). I have updated : `return 302 https://files.mydomain.com$1` (no slash before $1) . Please test and let me know. – Philippe May 22 '23 at 20:53
  • Philippe, unfortunately changing it to did not make any difference in behavior after changing the line in **UPDATE 4** to `return 302 https://files.mydomain.com$1;` First, I go to: `https://files.mydomain.com`. Then, I am presented with the login screen at: `https://files.mydomain.com/login.aspx`. When I enter my username/password, my browser immediately returns the following error: files.mydomain.com says HTTP Error: 200- (Response content-type in not application/json). – MKANET May 23 '23 at 02:58
  • @MKANET, in my country we say that, sometimes, "best" is the enemy of "good" (enough). **UPDATE 2** was almost perfect, I'm going to dig further more. – Philippe May 23 '23 at 05:10
  • @MKANET, may you have a look @ **UPDATE 5**? – Philippe May 23 '23 at 08:18
  • **UPDATE5** displays all files listed in the REAL path even with IIS directory browsing disabled. It bypasses IIS webserver completely. I am happy with "almost perfect" solution **UPDATE2**! I think you have earned it. Can you please edit your answer to ONLY show **UPDATE2** as the solution before I accept it as the answer? Or, edit it a little so its clearer that **UPDATE2** is the answer. It will be easier for others to see the answer in the future. – MKANET May 23 '23 at 15:49
  • @MKANET, I'm glad to read you ;) I edited the post with the finale answer at top, I don't know if is recommended on SO to delete all the consecutive answers. Probably yes, as they are useless. – Philippe May 23 '23 at 16:56
  • great job, you earned it. Nobody else was willing or able to figure this out... so, you deserve this bounty. – MKANET May 23 '23 at 20:33
  • @MKANET, many thanks for this and for your patience ;) Btw, I wonder if `location /files` with no trailing slash wouldn't be better in your case. If you have time to test it, please let me know. Thanks & all the best for you. – Philippe May 24 '23 at 01:48
  • Sure you're welcome. Removing the trailing slash for `location /files` didn't seem to change anything its behavior. It still has the small isshe. Do you think I should leave the `/` or remove it? I'm not sure what its for. – MKANET May 24 '23 at 02:00
  • In fact, I'm not sure either. It's beyond my knowledge :/ – Philippe May 24 '23 at 02:08
0

Try using a return and not a rewrite for a redirect. This should work:

location /path/to-your-page-name {
  return 301 /new-path/to-your-new-page-name;
}

So, if you want domains resolving to ~/files and assuming that root points to /inetpub/wwwroot do the following:

http {

server {        
        listen 80;
        server_name  localhost;
        return 301 https://$host$request_uri;
}

server {
        listen 80;
        server_name  files.mydomain.com;
        location / {
            return 301 https://files.mydomain.com$request_uri;
        }
}

server {
        listen 443 ssl http2; 
        listen [::]:443 ssl http2;
        server_name  files.mydomain.com;
        client_max_body_size 0;
        location / {
            return 301 https://files.mydomain.com/files;
        }
}

#Root Domain
server {
        listen 443 ssl http2; 
        listen [::]:443 ssl http2;
        server_name_in_redirect off;
        server_name  www.mydomain.com mydomain.com;
        log_not_found off;

    location / {
        #root   /inetpub/wwwroot;
        #index  index.html index.htm;
           return 301 https://files.mydomain.com/files;
        }
    }
}

You might also have to set server_name_in_redirect on; depending on your configuration.

I hope this helps!

  • thank you. Unfortunately, that just takes me to the "Welcome to NGINX webpage". – MKANET May 23 '23 at 15:39
  • @MKANET please check my new modified answer. –  May 23 '23 at 18:30
  • you are right `root` points to /inetpub/wwwroot, I tried your latest code _exactly_ like you have. I first cleared browser cache. When I enter `https//files.mydomain.com` in my web browser, it takes me to `https//files.mydomain.com/files` and get the browser error **EER_TOO_MANY_REDIRECTS**. Even it doesnt have an error, it doesn't go to the right URL. Also, when I go to my root domain: `https//mydomain.com`, it takes me to `https//files.mydomain.com` instead of `https//mydomain.com` and displays the same **EER_TOO_MANY_REDIRECTS**. Basically it broke everything – MKANET May 23 '23 at 20:29
  • Sorry, I couldn't put `:` in my previous comment.. I took them out to be able to post my comment. Thank you for trying though. – MKANET May 23 '23 at 20:30
  • I even tried `server_name_in_redirect on;` insetad of it being off. It make no difference. – MKANET May 23 '23 at 20:35