How to handle application level redirects in Nginx with Reverse Proxy
Asked Answered
A

3

6

I am writing an Nginx configurations for Crystal-Lang based application to send all the traffic http://example.com/videos/ to http://0.0.0.0:3000 via reverse proxy.

I have written the following config which is not working and I'm heading over the internet but no luck.

When I go to http://example.com/videos/, application internally performing a redirect from http://example.com/ to http://example.com/feed/popular which is the problem, it redirects to http://example.com/feed/popular which is wrong, I need /videos/ part to always concatenated with URL like http://example.com/videos/xxxx always but after redirect the /videos/ part is being chopped out. So the application should consider http://example.com/videos/ as host.

Here is my config:

server {
    listen 80;
    server_name elearn.com.pk default_server localhost;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    location /videos/ {
        proxy_pass http://0.0.0.0:3000/;
        proxy_http_version 1.1;
        rewrite /videos/(.*) /$1 break;
        proxy_redirect off;
        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/videos/;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
   }
}

Can someone please help me to resolve this issue please? Thanks.

Alms answered 12/10, 2021 at 5:43 Comment(3)
Where is feed/popular coming from?Trapezoid
from applicationAlms
same problem but still not find any solutionBalkh
B
1

You can use proxy_redirect to force change the header of Location the upstream returned redirect.

If I want nginx to dispatch the path foo to an upstream app with listen port is 7001, the simplest configure:

location /foo/ {
    proxy_pass  http://localhost:7001/;
}

However, for my situation, this reverse proxied upstream app will return a redirect of 301 Moved Permanently with header Location:/bar/ when user successfully login. (You can know how the redirect works by tracing network activity via DevTools of a browser.)

I want xxx.com/foo/bar => localhost:7001/bar, but because the incorrect Location of its redirect, by combing the host header it will return xxx.com/bar to clients. The problem is, it will require nginx to look location location /bar/ {...}, which is not configured at all.


Naturally, one brutal way in my head is to use another redirect to correct the url:

location / {
    ...
    rewrite /bar/.* /foo/bar/$1;
}
# OR
location /bar/ {
    return 301 $scheme://$http_host/foo/bar/;
}


After thinking, I realize a more favorable solution is to just change the Location of the returned redirect package directly. Fortunately, the proxy_redirect of nginx provides this function to allow us change the Location of proxied redirect.

Syntax: proxy_redirect redirect replacement;

from: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect.

OK, here is the solution:

location /foo/ {
    proxy_pass  http://localhost:7001/;
    proxy_redirect /bar/ /foo/bar/;
    # you may need to debug what content of "Location" in your wrong redirect package by DevTools, and replace it here.
}

A simply way to replace the wrong Location from /bar/ to /foo/bar/ the Location field fixed my problem.

PS: a trick of debuggin nginx and network activity is to use new “Incognito window” every time. Or the browser cache will give you misleading reaction.

Balkh answered 4/8, 2022 at 10:40 Comment(0)
E
0

Assuming the redirect comes from the proxied application, you need to rewrite the Location header to match the prefix path on the proxy server.

proxy_redirect off is causing this error. You need to set it to default or configure a custom rewrite (default should work fine for your purpose, though).

Edict answered 12/10, 2021 at 9:27 Comment(2)
Hello I'm new to nginx, would you please include the exact solution to your answer please? that would be more beneficial for the people have this issue.Alms
All the necessary information is available in the referenced documentation. Easiest solution is to just remove this line. If you can't parse the nginx documentation, I'd suggest to reconsider if you should really be running this software.Karyogamy
R
0

You should define upstream in http directive.

http {
# ...

  upstream myapp {
    server 0.0.0.0:3000;
  }

# ...

}

Then use it in the server scope in location like this:

location ^~ /video/ {
  proxy_pass http://myapp;
}
Rudolph answered 19/10, 2021 at 19:39 Comment(1)
not work for meBalkh

© 2022 - 2024 — McMap. All rights reserved.