nginx rewrite url without changing browser address

16,340

Your rewrite logic is fine since its working correctly in normal schenerio. Browser URL is changing for 302 redirect because rewrite directive just changes the request URI, not the response of request.

A typical 302 reponse looks like this:

HTTP/1.1 302 Found
Location: http://overrideurlrewriting.com

Location header in 302 response forces the browser to follow mentioned url.

Possible solution is to modify Location header from the proxied response (in case of 302 redirect) using proxy_redirect directive

Helpful links:

https://stackoverflow.com/a/26025618/2073920

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

Share:
16,340

Related videos on Youtube

Syed Osama Maruf
Author by

Syed Osama Maruf

Updated on September 18, 2022

Comments

  • Syed Osama Maruf
    Syed Osama Maruf over 1 year

    I want to change the url of a request but the browser address should not change. To achieve this I have tried the below configuration:

    location /my-website {          
    
        proxy_pass  http://tomcat/my-website;
    }
    
    location =/my-website { 
    
            rewrite /my-website$(.*) $1/my-website/mypage/index.html last;
    
    }
    

    Although doing this the request does get the correct address but the address bar of the browser also changes.

    Also tried;

    location /my-website {                  
        proxy_pass  http://tomcat;
        rewrite /my-website$(.*) $1/my-website/page/index.html break;
    
    }
    

    Any suggestion(s) on improving this configuration?

    Expected Output

    address bar: protocol://localhost/my-website

    actual: protocol://localhost/my-website/page

    Current Output

    address bar: protocol://localhost/my-website/page

    actual: protocol://localhost/my-website/page

    Things tried :

    Edit

    The above issue is being faced on a 302 redirect. For other cases the url is changed without changing the browser address. I am handling the latter case using the below config:

    location /my-website {      
    
            proxy_pass  http://tomcat;
            rewrite ^(.*)my-website/src(.*)$ $1my-website/page/src$2 break;
    
    
        }
    

    i.e. that location is followed by /src and it works.

    In the 302 case the location is just my-website/ and the above tried things fail.

    My file config:

    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
    
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"' 
                          '"$upstream_http_location"';    
    
        rewrite_log  on;
    
        #log_format  graylog2_format  '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" <msec=$msec|connection=$connection|connection_requests=$connection_requests|millis=$request_time>';
    
        error_log logs/error.log warn;
    
        sendfile        on;
    
        keepalive_timeout  65;
    
        map $http_user_agent $ua_redirect {
        default 'abc';        
        }
    
    
    
        upstream docker-mysite {
            server localhost:9012;
        }
    
    
        proxy_set_header     Host $host;
        proxy_set_header     X-Real-IP $remote_addr;
        proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header     X-Forwarded-Host $server_name;
        proxy_set_header     X-Forwarded-Proto $scheme;
        proxy_read_timeout   900;
    
        client_max_body_size 0; 
    
    server {
        listen       80;      
    
    
        access_log  logs/host.access.log  main; 
    
        #below config works
        location /mysite {                      
            proxy_pass  http://docker-mysite;
            rewrite ^(.*)mysite/src(.*)$ $1mysite/$ua_redirect/src$2 break;
    
        }
        #below config works but modifies the browser url hence the issue
        location = /mysite {    
            proxy_pass  http://docker-mysite;               
            rewrite /mysite(.*)$ /mysite/$ua_redirect$1 break;
    
        }
    
    }
    
    }
    

    Logs

    127.0.0.1 - - [03/Sep/2018:11:46:07 +0500] "GET /mysite/login?code=token HTTP/1.1" 302 0 "http://localhost/loginapp/web/index.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" "-"http://localhost/mysite/abc
    127.0.0.1 - - [03/Sep/2018:11:46:07 +0500] "GET /mysite/abc HTTP/1.1" 404 0 "http://localhost/loginapp/web/index.html" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" "-"-
    
  • Rhys
    Rhys over 5 years
    To extend on this answer: Your rewrite of rewrite /my-website$(.*) is basically saying that the URL ends at /my-website as $ is the symbol for end-of-line in PCRE. Nginx uses the PCRE library during compilation. A good place to test out your regex is at regex101.com
  • Syed Osama Maruf
    Syed Osama Maruf over 5 years
    just tried your solution. the url is correctly re written however the browser address is also changed. i don't know if it will help but the re write is to happen on a 302 server redirect. For other cases the following config works fine proxy_pass docker-iam; rewrite ^(.*)iam/src(.*)$ $1iam/$ua_redirect/src$2 break;
  • Syed Osama Maruf
    Syed Osama Maruf over 5 years
    i will add this to the question as well