Score:1

Nginx proxy_redirect with relative paths

gq flag

I am not a big specialist in nginx administration, I am just a developer. I have two backends running in docker. Let me name them

  • backend1:8080
  • backend2:8081

Also I have Nginx exposing 443 port with letsencrypt certificated installed. My configuration of Nginx is (env variable FQDN is something like example.com)

upstream backend1 {
  server backend1:8080;
}

upstream backend2 {
  server backend2:8081;
}

server {
  listen 443 ssl;
  
  server_name ${FQDN} www.${FQDN};
  
  ssl_certificate /etc/letsencrypt/live/${FQDN}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/${FQDN}/privkey.pem;
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout  5m;
  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers   on;

  if ($server_port = 80) { set $https_redirect 1; }
  if ($host ~ '^www\.') { set $https_redirect 1; }
  if ($https_redirect = 1) { return 301 https://${FQDN}$request_uri; }
  
  location /path1/ {
    
    proxy_pass http://backend1/;

    proxy_redirect ~^/(.*) $scheme://$http_host/path1/$1;
    
    proxy_http_version 1.1;
    
    proxy_pass_header Set-Cookie;
    proxy_pass_header Cookie;
    proxy_pass_header X-Forwarded-For;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forward-Proto http;
    proxy_set_header X-Nginx-Proxy true;
    add_header       X-Upstream      $upstream_addr;
  }
  
  location /path2/ {
    
    proxy_pass http://backend2/;

    proxy_redirect ~^/(.*) $scheme://$http_host/path2/$1;
    
    proxy_http_version 1.1;
    
    proxy_pass_header Set-Cookie;
    proxy_pass_header Cookie;
    proxy_pass_header X-Forwarded-For;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forward-Proto http;
    proxy_set_header X-Nginx-Proxy true;
    add_header       X-Upstream      $upstream_addr;
  }
}

I want that if I request https://exapmle.com/path1/ then Nginx should go to http://backend1:8080/ and return me response from that server. The problem is that backend1 (as well as backend2) can response with 302 and redirect to some path eg. /login. Nginx redirects my browser to https://exapmle.com/login but I want it to redirect me to https://exapmle.com/path1/login Could you help me please and point to the error that I made in my configuration. I've reviwed all similar questions in SO and not found any solution. Also I've explored Nginx documentation and also have not found the answer.

I have the line proxy_redirect ~^/(.*) $scheme://$http_host/path1/$1; and I suppose it must do the work I want.

BTW I cannot occupy / location (create configuration for the root path) in my Nginx config as it is reserved to another backend server. Thanks in advance.

Richard Smith avatar
jp flag
The first parameter of the `proxy_redirect` statement must match the text string returned in the `Location` header of the 302 response. You should use `curl -I` to identify the exact text of the header.
Michael Hampton avatar
cz flag
You must configure your backend application to generate such URLs. It does not know that you are serving its routes at /path1 (or /path2 or whatever) unless you explicitly told it.
Herman Sid avatar
gq flag
@MichaelHampton Unfortunately these backends are not configurable for proxy usage. They are 3d party applications and do not have any settings for that.
Herman Sid avatar
gq flag
@RichardSmith Yes I think the same. My 'proxy_redirect' regex is not being hit by returned redirection location. I've checked and found, that backend responses with '/login' in Location header. Nginx merge it with domain name and I get 'https://example.com/login'. Thus Nginx does not match it with '~^/(.*)' and does not add prefix.
Score:0
jp flag

Maybe it is because of the misspelled X-Forwarded-Headers in your configuration. It should be X-Forwarded-* instead of X-Forward-*.

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.