在nginx location中用alias代理檔案

雲荒杯傾發表於2019-01-19

介紹nginx中location塊的匹配符(~, ~*, ^~, [space]等)與alias檔案代理的關係

實驗環境

靜態資源目錄

E: /static

  • a.js
  • b.js
  • /case/

    • c.js
    • d.js
    • e.js
nginx server塊
server {
    listen       80;
    server_name  127.0.0.1;
}

alias代理特定檔案

僅僅代理一個特定的檔案,基本上很少會出錯,
location塊是字首匹配和正則匹配均可。
如下,瀏覽器訪問http://127.0.0.1/static/case/… 都返回c.js的內容。

    location /static/case/c.js {
        alias E:/static/case/c.js;
    }
    location ~ /static/case/c.js {
        alias E:/static/case/c.js;
    }

alias代理某目錄下的各個檔案

但當需要代理一個目錄下的各個檔案時,會因location塊是字首匹配和正則匹配的不同,導致代理的結果不同。
尤其是location是正則匹配時,較為特殊,容易出錯。

location是字首匹配^~或者[space]時

這種情況如果出錯,一般就是由於對location URI部分和alias部分最後加不加“/”犯糊塗導致的,
或者說是不清楚這種情況下最終代理到什麼path導致的。

// case1
location /static/case/ {
    alias E:/static/case/;
    autoindex on;
}
// case2
location /static/case {
    alias E:/static/case/;
    autoindex on;
}
case3
location /static/case/ {
    alias E:/static/case;
    autoindex on;
}
case4
location /static/case {
    alias E:/static/case;
    autoindex on;
}

以上四種情況,瀏覽器輸入:http://127.0.0.1/static/case/… 只有第三種失敗。
如果在這四種情況的location前面都加上 ^~ 結果也是一樣的,因為 ^~ 和[space]都是字首匹配。

**最終代理路徑是: alias路徑 + location部分URI和瀏覽器輸入的URL未匹配到的部分。
這個路徑下有檔案,就200,沒有檔案,就404。**
所以分析一下為什麼第三種寫法不能正確代理呢,
瀏覽器URL: http://127.0.0.1/static/case/…
location:/static/case/,
因此兩個URL匹配部分是/static/case/,
未匹配部分是c.js。
因此它最終代理的path是:E:/static/case + c.js = E:/static/casec.js,相當於找static目錄下有沒有casec.js檔案,因為沒這個檔案,所以404。

location是正則匹配~, ~*時
    location ~ /static/case/ {
        alias E:/static/case/;
        autoindex on;
    }

瀏覽器URL1:http://127.0.0.1/static/case/…
瀏覽器URL2:http://127.0.0.1/static/case/…
瀏覽器URL3:http://127.0.0.1/static/case/…
瀏覽器URL4:http://127.0.0.1/static/case/,
結果都是一樣的,返回/static/case目錄。
其中只有URL4,直接200返回。URL1-3都是301->200。

重定向不是無限的,當瀏覽器URL case後的層級大於10時,就不再301->200,而是直接200返回。
即,瀏覽器URL5,直接200返回。代理到/static/case目錄。
瀏覽器URL5:http://127.0.0.1/static/case/…

因此,代理目錄時,location還是正則匹配的話,是無法訪問到這個目錄下的各個檔案的。

解決辦法有兩個。

    關於既想用~又想能代理到某目錄下各個檔案的解決辦法:
    //方案1
    location ~ ^/(.+)/(.+)/(.+.js)$ {
        alias E:/static/case/$3;
    }
    //方案2、用root結合rewrite代替
    location ~ ^/.+/.+/.+.js$ {
        root E:/;
        rewrite ^/(.*) /$1 break;
    }

相關文章