最近的一個項目,需要特定的IP訪問某專題頁面的時候跳轉到網站首頁,思考了下,直接使用nginx實現,分享給大家。
業務需求
業務和開發同事需要我這邊做一條規則,所有訪問 ip 為非上海、廣州 office 外網 ip,url 為http://test.com/fuck/index.html?的請求都跳轉到?http://test.com/index.html?。然后所有在上海和廣州 office 的外網 IP 訪問?http://test.com/fuck/index.html?依然還是?http://test.com/fuck/index.html。這樣就可以在生產上做隔離,不影響其他用戶的服務。
注:因為目前生產上的 Nginx 沒有做 lua 支持,所以就無法通過使用 lua 來實現該需求,也沒有安裝 geoip ,所以也無法用模塊來支持,只能原生的。
原始的 nginx 配置
upstream?service_test?{ ?????server?127.0.0.1:8080; } server ?{ ??listen????80; ??server_name?test.com; ??index?index.html?index.php; ??root?/tmp/test.com; ??error_page?404?http://test.com/404.html; ??error_page?502?http://test.com/502.html; ??error_page?500?http://test.com/500.html; ??location?~*?.(gif|jpg|jpeg|png|css|js|ico|txt|svg|woff|ttf|eot)$ ??{ ????rewrite?^(.*)$?/static$1?break; ????root?/tmp/test.com;?#? ????expires?1d; ??} ??location?~*?.(html|htm)$ ??{ ????rewrite?^(.*)$?/static$1?break; ????roo?/tmp/test.com;?#? ????expires?900s; ??} ??location?/?{ ?????proxy_pass?http://service_test; ?????include?/opt/conf/nginx/proxy.conf; ??}
修改后的 Nginx 配置
upstream?service_test?{ ?????server?127.0.0.1:8080; } server ?{ ??listen????80; ??server_name?test.com; ??index?index.html?index.php; ??root?/tmp/test.com; ??error_page?404?http://test.com/404.html; ??error_page?502?http://test.com/502.html; ??error_page?500?http://test.com/500.html; ??location?~*?.(gif|jpg|jpeg|png|css|js|ico|txt|svg|woff|ttf|eot)$ ??{ ????rewrite?^(.*)$?/static$1?break; ????root?/tmp/test.com;?#? ????expires?1d; ??} ??location?~*?.(html|htm)$ ??{ ????rewrite?^(.*)$?/static$1?break; ????roo?/tmp/test.com;?#? ????expires?900s; ??} ??set?$flag?0; ??if?($request_uri?~*?"^/fuck/w+.html$")?{ ??????set?$flag?"${flag}1"; ??} ??if?($remote_addr?!~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ????set?$flag?"${flag}2"; ??} ??if?($flag?=?"012")?{ ????rewrite?^?/index.html?permanent; ??} ??location?/?{ ?????proxy_pass?http://service_test; ?????include?/opt/conf/nginx/proxy.conf; ??}
在實現需求的過程中出現的問題
把 if 指令 和 proxy_pass 都放在 location 下面的話,if 指令里面的內容不會執行,只會執行 proxy_pass。
location?/?{ ???if?($remote_addr?!~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ??????rewrite?^?/index.html?permanent; ???} ???proxy_pass?http://service_test; ???include?/opt/conf/nginx/proxy.conf; }
if 指令下面使用 proxy_pass 指令問題
像下面這樣使用會報錯,錯誤的方式:
????if?($remote_addr?~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ??????proxy_pass?http://test.com/fuck; ????}
正確的方式:
????if?($remote_addr?~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ??????proxy_pass?http://test.com$request_uri; ????}
或是
????if?($remote_addr?~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ??????proxy_pass?http://test.com; ????}
如果你是直接另外啟動一個 location 的話,比如啟動如下 location :
??location?/fund?{ ?????if?($remote_addr?!~*?"192.168.0.50|192.168.0.51|192.168.0.56")?{ ????????rewrite?^?/index.html?permanent; ?????} ??}
這樣的方式也是不支持的,當用 IP 192.168.0.50 訪問的時候,沒有達到我們的業務需求,會報錯 400
注:各位有其他好的建議,歡迎探討。
更多Nginx相關技術文章,請訪問Nginx教程欄目進行學習!