1. 程式人生 > >nginx proxy_pass和rewrite的區別

nginx proxy_pass和rewrite的區別

nginx proxy_pass和rew

rewrite

syntax: rewrite regex replacement [flag]
Default: —
Context: server, location, if
  • 如果正則表達式(regex)匹配到了請求的URI(request URI),這個URI會被後面的replacement替換

  • rewrite的定向會根據他們在配置文件中出現的順序依次執行

  • 通過使用flag可以終止定向後進一步的處理

  • 如果replacement以“http://”, “https://”, or “$scheme”開頭,處理將會終止,請求結果會以重定向的形式返回給客戶端(client)

  • 如果replacement字符串裏有新的request參數,那麽之前的參數會附加到其後面,如果要避免這種情況,那就在replacement

    字符串後面加上“?”,eg:

     rewrite ^/users/(.*)$ /show?user=$1? last;=
  • 如果正則表達式(regex)裏包含“}” or “;”字符,需要用單引號或者雙引號把正則表達式引起來

  • 要把 http://www.test.com/a/b?id=123 的一條鏈接轉換成 http://www.test.com/p-123.html

  • 在nginx中是有特殊邏輯,它用$query_string來表示問號以後的字符,即"id=123"

  • if ($request_uri ~* "^/a/b\?id=(\d+)$") {
    set $myarg1 $1;

    rewrite .* http://www.test.com/p-$myarg1.html? permanent;
    }

  • 註意,set $myarg1 $1; 這句話不能少,不能直接用$1,會出錯的。

可選的flag參數如下:

  • last

  1. 結束當前的請求處理,用替換後的URI重新匹配location;

  2. 可理解為重寫(rewrite)後,發起了一個新請求,進入server模塊,匹配location;

  3. 如果重新匹配循環的次數超過10次,nginx會返回500錯誤;

  4. 返回302 http狀態碼 ;

  5. 瀏覽器地址欄顯示重地向後的url

  • break

  1. 結束當前的請求處理,使用當前資源,不在執行location裏余下的語句;

  2. 返回302 http狀態碼 ;

  3. 瀏覽器地址欄顯示重地向後的url

  • redirect

  1. 臨時跳轉,返回302 http狀態碼;

  2. 瀏覽器地址欄顯示重地向後的url

  • permanent

  1. 永久跳轉,返回301 http狀態碼;

  2. 瀏覽器地址欄顯示重定向後的url

proxy_pass

Syntax:    proxy_pass URL;
Default:    —
Context:    location, if in location, limit_except
  • 不影響瀏覽器地址欄的url

  • 設置被代理server的協議和地址,URI可選(可以有,也可以沒有)

  • 協議可以為http或https

  • 地址可以為域名或者IP,端口可選;eg:

     proxy_pass http://localhost:8000/uri/;
  • 如果一個域名可以解析到多個地址,那麽這些地址會被輪流使用,此外,還可以把一個地址指定為 server group(如:nginx的upstream), eg:

    技術分享圖片

    upstream backend {
        server backend1.example.com       weight=5;
        server backend2.example.com:8080;
        server unix:/tmp/backend3;
     
        server backup1.example.com:8080   backup;
        server backup2.example.com:8080   backup;
    }
     
    server {
        location / {
            proxy_pass http://backend;    }
    }

    技術分享圖片

  • server name, port, URI支持變量的形式,eg:

    proxy_pass http://$host$uri;

這種情況下,nginx會在server groups(upstream後端server)裏搜索server name,如果沒有找到,會用dns解析

請求的URI按照下面的規則傳給後端server

  1. 如果proxy_pass的URL定向裏包括URI,那麽請求中匹配到location中URI的部分會被proxy_pass後面URL中的URI替換,eg:

    location /name/ {
        proxy_pass http://127.0.0.1/remote/;}
    請求http://127.0.0.1/name/test.html 會被代理到http://example.com/remote/test.html
  2. 如果proxy_pass的URL定向裏不包括URI,那麽請求中的URI會保持原樣傳送給後端server,eg:

    location /name/ {
        proxy_pass http://127.0.0.1;}
    
    請求http://127.0.0.1/name/test.html 會被代理到http://127.0.0.1/name/test.html
  3. 一些情況下,不能確定替換的URI

    1. location裏是正則表達式,這種情況下,proxy_pass裏最好不要有URI

    2. 在proxy_pass前面用了rewrite,如下,這種情況下,proxy_pass是無效的,eg:

      location /name/ {
          rewrite    /name/([^/]+) /users?name=$1 break;
          proxy_pass http://127.0.0.1;}


重寫規則語法: rewrite 正則 替換 標誌位

(1). 任何重寫規則第一部分肯定是 正則表達式


可以用()來捕獲正則表達式,然後在rewrite後面就用 $[d+] 來用這個正則表達式;比如:


^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$   ---->http://xxxx.com/images/aa/abc01/test.gif   
#其中   
$1=([a-z]{2})      #$1=aa  
$2=([a-z0-9]{5})   #$2=abc01  
$3=(.*)            #$3=test  
$4=(png|jpg|gif)   #$4=gif

上面的4個地段都是query 串中匹配的字符串


(2). 重寫規則的第二部分是URI(rewrite 重寫後url)

query 請求串被改寫,包括上面正則表達式獲取的參數字段和nginx 相關的配置,

/data?file=$3.$4   # rewrite之後的query http://data?file=test.gif

rewrite 之後會返回給客戶端301 或者302 [ 會不會返回200]

(3). 重寫規則的第三部分是:尾部的標記 flag last return break


laster 標記之後會從新loaction ,繼續rewrite 最多10次


rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4 last;  
#<pre name="code" class="html">http://xxxx.com/images/aa/abc01/test.gif   -----rewrite---> http://data?file=test.gif


break標記是直接跳槽rewrite和localtion 進行query的處理if ($bwhog) {


if ($bwhog) {  
    limit_rate 300k;  
    break;  
}

return標記停止rewrite 處理指令,進而控制主HTTP 模塊處理請求,也就是HTTP請求也不處理了,直接給client 返回(結合error0page,)


location = /image404.html {  
    return 404 "image not found\n";  
}

(4). 整個過程的實例


http {  
    server {  
        root /home/www;  
   
        location / {  
                # 重寫規則信息  
                error_log logs/rewrite.log notice;   
                # 註意這裏要用‘’單引號引起來,避免{}  
                rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;  
                # 註意不能在上面這條規則後面加上“last”參數,否則下面的set指令不會執行  
                set $image_file $3;  
                set $image_type $4;  
        }  
   
        location /data {  
                 
                rewrite /data?(.*) /error/img=$1 break;  #break 就是最後的rewrite 結果,不會再次遍歷localtion啦  
        }  
        location = /error/ {  
                # 圖片不存在返回特定的信息  
                return 404 "image not found\n";  #如果是return HTTP 直接返回403 302 等狀態碼  
        }  
}


本文參考

https://blog.csdn.net/caoshuming_500/article/details/37700357

https://www.cnblogs.com/luxianghao/p/6807081.html


nginx proxy_pass和rewrite的區別