Nginx學(xué)習(xí):目錄索引、字符集與瀏覽器判斷模塊今天要學(xué)習(xí)的內(nèi)容有幾個(gè)還是大家比較常見的,所以學(xué)習(xí)起來也不會(huì)特別費(fèi)勁。對于目錄的默認(rèn)頁設(shè)置大家都不會(huì)陌生,字符集的設(shè)置也比較常見,而瀏覽器的判斷這一塊,可能有同學(xué)會(huì)接觸過針對 IE 瀏覽器的一些特殊設(shè)置。今天的內(nèi)容也基本上都是可以在 http、server、location 中可以進(jìn)行配置的,只有一個(gè)指令是只能在 http 中配置的,到時(shí)候會(huì)單獨(dú)說。 默認(rèn)頁 index沒錯(cuò),就是那個(gè)最常見的 index 指令,它是單獨(dú)的屬于 ngx_http_index_module 模塊,不需要編譯,是核心源碼中的一個(gè)配置指令。不管是默認(rèn)的 nginx.conf 還是用一些面板工具安裝的 Nginx ,都會(huì)有這個(gè)指令的出現(xiàn)。
這就是默認(rèn)配置中給的 index 指令的配置,如果是 PHP 環(huán)境,通常會(huì)把 index.php 放在前面。它的配置參數(shù)非常簡單。
默認(rèn)值是 index.html ,所以如果是靜態(tài)頁面,并且本身就有 index.html 這個(gè)文件的話,不配這個(gè)指令也行。它的作用就是定義如果是以 / 結(jié)尾的 location 路徑,也就是目錄路徑,就會(huì)按照配置的順序檢查文件。比如上面的默認(rèn)配置中,如果在 root 指定的根目錄下沒有 index.html 文件,就會(huì)找 index.htm 文件。如果有 index.html ,就直接會(huì)返回 index.html 文件了。那么如果這兩個(gè)文件都找不到呢?404 唄。不過它還可以在最后一個(gè)元素帶上一個(gè)有路徑的文件,比如 /index.html ?,F(xiàn)在我們就來配一個(gè)。
注意,我們要在 root 指定的目錄下創(chuàng)建一個(gè) indextest 目錄,否則即使最后有一個(gè) /index.html ,也會(huì)一直是 404 。
現(xiàn)在這個(gè)目錄里面沒有配置中指定的這些文件,直接訪問的話,就會(huì)返回根目錄的首頁文件。 接著我們可以一個(gè)一個(gè)地創(chuàng)建,比如先創(chuàng)建一個(gè) a.txt ,再次訪問,就會(huì)顯示 a.txt 中的內(nèi)容。這里的文件是可以自由定義的,不僅是 html 或者 txt 文本,php 之類的腳本文件都是可以的,前提是也要配好 FastCGI 。 另外需要注意的是,index 文件會(huì)引發(fā)內(nèi)部重定向,請求可能會(huì)被其它 location 處理。 比如,下面這個(gè)例子:
請求 “/” 實(shí)際上將會(huì)在第二個(gè) location 中作為 /index.html 被處理。這一段是官網(wǎng)的例子,我沒有測試,其實(shí)就是 location 規(guī)則的問題。大家可以自己試試,意思就是 / 會(huì)變成 /index.html ,然后交由下面的 location 進(jìn)行處理。 目錄索引有的時(shí)候,我們不指定 index ,而是需要直接列出整個(gè)目錄里面的文件內(nèi)容,就像一些開源代碼的下載地址。比如說 Hadoop 的下載地址:https://archive./dist/hadoop/common/ 在 Apache 中,也有類似的設(shè)置,而在 Nginx 中,只需要啟用 ngx_http_autoindex_module 模塊就可以了。這個(gè)模塊也是核心源碼中的,直接就可以使用。首先,還是要準(zhǔn)備一些文件,比如可以用 shell 直接生成一些。
然后,就簡單地配置一下,還是使用上面的 indextest 目錄。
接下來直接訪問 /indextest/ 路徑,就可以看到下面的內(nèi)容。 直接點(diǎn)擊文件就可以打開訪問對應(yīng)的文件啦。 autoindex開啟或者關(guān)閉列出目錄中文件的功能。
默認(rèn)是 off ,當(dāng)然是不能隨便把目錄中所有的文件信息都暴露出來啦,因此,大部分情況下都只是特殊的一些目錄才會(huì)用到。如果是 off ,并且沒有 index ,也沒有 index.html 的話,那就是 404 。 autoindex_exact_size設(shè)置目錄中列出的文件是顯示精確大小,還是對KB,MB,GB進(jìn)行四舍五入。
默認(rèn)是 on ,也就是精確顯示大小,設(shè)置成 off 的話,就會(huì)進(jìn)行四舍五入帶單位的顯示。同時(shí),它還必須是下面的 autoindex_format 設(shè)置為 html 時(shí)才會(huì)有效果。最后我們會(huì)一起看例子。 autoindex_format設(shè)置索引目錄展示的形式。
默認(rèn)是 html ,就是我們上面看到的那個(gè)樣子,還可以換成別的形式。后面我們一起測試時(shí)看效果。 autoindex_localtime設(shè)置目錄中列出文件的時(shí)間是本地時(shí)間還是UTC時(shí)間。
默認(rèn)值是 off ,使用的是 UTC 時(shí)間,改成 on 之后,就是服務(wù)器的時(shí)間。 綜合測試現(xiàn)在直接配置上除上面的例子中沒用到的那三個(gè)指令吧,如果是 on 的就換成 off ,off 的就換成 on ,html 也換成 json 。
看看效果,輸出的結(jié)果是不是變成了下面這樣的 json 格式了。 但是大家會(huì)發(fā)現(xiàn),size 表示的文件大小沒有變化呀,前面說過了,autoindex_exact_size 只有在 html 的時(shí)候才會(huì)有效果。因此,我們還是要把 autoindex_format 換回 html ,這樣就可以看到大小顯示的結(jié)果也不一樣了。 字符集 Charset字符集的模塊全名是 ngx_http_charset_module 模塊。記得剛開始學(xué) PHP 的時(shí)候,還是 PHP 剛剛升級(jí)到 5 的時(shí)候,5.2 或者 5.1 是主流版本,MySQL 也是同樣的剛到 5 左右的版本。在哪個(gè)時(shí)代,Discuz 或者 DedeCMS 這些開源程序都會(huì)提供 UTF8 和 GBK 兩種版本,是不是感覺怪怪的,因?yàn)楫?dāng)時(shí) UTF8 還沒有一統(tǒng)天下嘛。 到了現(xiàn)在,基本上不管是什么軟件,PHP的編輯器創(chuàng)建的文件、MySQL建庫建表、Redis、Go語言、Java、前端,等等等等,默認(rèn)全是 UTF8 了,因此,字符集會(huì)產(chǎn)生的亂碼問題說實(shí)話已經(jīng)大大減少了。包括在 Nginx 中,默認(rèn)的配置文件中那個(gè)默認(rèn)的 server 里面,第四行就是一個(gè)被注釋掉的 咱們的測試,就設(shè)置一個(gè) gbk ,讓 utf8 亂碼好了,默認(rèn)的 koi8-r 我都不知道是哪里的語言編碼....
繼續(xù)復(fù)用上面的 /indextest/ 這個(gè)路徑,在 location 添加上面的這條配置指令。然后隨便建立一個(gè)文件,并且在里面寫中文,看看訪問結(jié)果是不是亂碼了。其實(shí)呀,這個(gè)指令的意思是在響應(yīng)頭的 Content-type 中添加上 charset 參數(shù)。 默認(rèn)情況下,我們訪問的普通 Nginx 靜態(tài)頁面返回的 Content-type 就是一個(gè) text/html ,而設(shè)置了 charset 之后,就變成了
當(dāng)使用代理或者 FastCGI 時(shí),默認(rèn)情況下會(huì)直接使用它們返回的響應(yīng)頭中的 Content-type 。 charset為響應(yīng)頭的 “Content-Type” 添加指定的字符集。
現(xiàn)在的默認(rèn)值就是 off ,表明不在響應(yīng)頭的 “Content-Type” 中添加字符集。如果這個(gè)字符集和 source_charset 指令設(shè)置的字符集不同,就會(huì)進(jìn)行轉(zhuǎn)換。這個(gè)指令后面馬上就會(huì)說。 它的參數(shù)也可以使用變量來指定,參數(shù)可以使用的值需要符合 charset_map 或 source_charset 的值。此外,字符集也可以在響應(yīng)頭的 “X-Accel-Charset” 中設(shè)置。 這個(gè)功能可以使用 proxy_ignore_headers和 fastcgi_ignore_headers 指令來禁用。 charset_map描述了從一個(gè)字符集到另一個(gè)字符集的轉(zhuǎn)換表。這個(gè)配置指令只能配置在 http 模塊中,不能放到 server 或 location 里面。
默認(rèn)值是空的,意思就是從 charset1 到 charset2 的轉(zhuǎn)換,比如說 UTF8 到 GBK 的轉(zhuǎn)換規(guī)則,配置比較復(fù)雜,比如這樣:
我們下載的安裝包中已經(jīng)提供了從 charset_types使模塊在響應(yīng)時(shí)能處理除了 “text/html” 之外其他指定的MIME類型。
默認(rèn)值包含 text/html text/xml text/plain text/vnd.wap.wml application/x-javascript application/rss+xml 這些。這個(gè)配置其實(shí)和我們上篇文章中學(xué)過的 addition_types 一樣,就是說這些類型的會(huì)讓 charset 指令產(chǎn)生效果,如果有特殊需求可以再繼續(xù)添加。 override_charset對于接收到的代理服務(wù)器或者 FastCGI 服務(wù)器的響應(yīng)頭中 “Content-Type” 已經(jīng)帶有字符集的情況,確定是否進(jìn)行字符集轉(zhuǎn)換。
默認(rèn)值是 on ,如果開啟轉(zhuǎn)換,接收到的響應(yīng)中指定的字符集會(huì)被當(dāng)作原始字符集。如果在子請求中接收到的應(yīng)答,始終會(huì)將應(yīng)答的字符集轉(zhuǎn)換為主請求的字符集,無論 override_charset 指令是否開啟。 我拿 PHP 試了,沒啥效果,會(huì)直接報(bào) 500 錯(cuò)誤,PHP 中使用 header 指定字符集為 UTF8 ,然后 Nginx 中設(shè)置的 Charset 還是 gbk 。錯(cuò)誤信息是指定的字符集在 charset_map 或 source_charset 中不存在。也沒找到合適的 UTF8 轉(zhuǎn)換 GBK 的 charset_map 文件,所以這一塊也就不知道怎么繼續(xù)測試?yán)?。有了解的小伙伴記得評(píng)論留言哦。 source_charset定義響應(yīng)中的原始字符集。
默認(rèn)是空的,沒有設(shè)置。如果這個(gè)指令配置的字符集與 charset 配置的不一樣,就會(huì)進(jìn)行轉(zhuǎn)換。 瀏覽器判斷 browser在瀏覽器判斷的 ngx_http_browser_module 模塊中,有一個(gè)變量你肯定見過,那就是 除了這個(gè)變量之外,這個(gè)模塊里面還提供了三個(gè)變量,另外還有幾個(gè)指令,是對這幾個(gè)變量進(jìn)行配置以及賦值的。也就是說,整個(gè)模塊其實(shí)都圍繞下面的這三個(gè)變量。
這些變量有啥用呢?別急,后面測試的時(shí)候再看,先來看看在這個(gè)模塊中的配置指令,一共就四個(gè)。 ancient_browser如果任一指定的子串在請求頭的“User-Agent”域中被發(fā)現(xiàn),瀏覽器將被認(rèn)定為舊式瀏覽器。
它的默認(rèn)值是空的,沒有默認(rèn)值,而另外一個(gè) ancient_browser_value 配置的默認(rèn)值是 1 ,也就說,如果使用普通的 if 不帶等于的進(jìn)行布爾判斷,那么 ancient_browser_value設(shè)定變量
上個(gè)指令中就介紹過了,它的默認(rèn)值是 1 ,當(dāng)然也可以設(shè)置成別的值,而且不一定是數(shù)字,字符串也可以??梢杂迷?if 判斷上。但是如果直接設(shè)置了這個(gè)值,那么后續(xù)任何別的操作都沒用了, modern_browser指定一個(gè)版本,此版本及后續(xù)版本的瀏覽器都被認(rèn)定為新式瀏覽器。
瀏覽器可以是下列之一: msie, gecko (基于Mozilla), opera,safari, 或者 konqueror 。注意這里沒有 Chrome 哦,Chrome 也是基于 Mozilla 的,因此用 gecko 就可以了。 版本可被指定為以下形式:X, X.X, X.X.X, 或 X.X.X.X。 每一形式的最大值分別是4000, 4000.99, 4000.99.99, 和 4000.99.99.99 。 如果瀏覽器既沒有在 modern_browser 中列出,又沒有在 ancient_browser 中列出時(shí),并且配置了特殊值 unlisted ,那么瀏覽器將被認(rèn)定為新式瀏覽器,否則認(rèn)定為舊式瀏覽器。 如果請求頭中沒有 “User-Agent” 域,瀏覽器以沒有列出對待。 看著有點(diǎn)懵吧?其實(shí)它就是和 ancient_browser 反過來的,馬上在例子中我們就可以看到效果。 modern_browser_value設(shè)定變量
和 ancient_browser_value 的意思是一樣的,它的默認(rèn)值同樣也是 1 ,但是,注意 modern_browser 定義中說的那些內(nèi)容,如果是默認(rèn)情況下,modern_browser 是空的,即使你下載最新版本的瀏覽器也不會(huì)判斷為新式瀏覽器,因此,最終 測試 browser看上面的變量和配置項(xiàng)有點(diǎn)暈吧?其實(shí)這一塊就是幫助我們用自己定義的標(biāo)準(zhǔn)來判斷指定的瀏覽器,將這個(gè)瀏覽器歸屬到 新式 或 舊式 瀏覽器這兩個(gè)陣營中。然后使用兩個(gè)變量就可以通過 Nginx 中的編程語法,比如 if 來進(jìn)行一些特殊的判斷。
在上面的例子中,先不看注釋的部分。modern_browser 我們設(shè)置了一個(gè) safari ,版本號(hào)是 600.0.0 ,意思就是只要是大于等于這個(gè)版本的 safari 瀏覽器,就會(huì)判定為新式瀏覽器, 怎么測試呢?我們可以通過 Postman 來重寫請求頭的 User-Agent 字段實(shí)現(xiàn)。 這一大串的字符怎么來的?拿真的瀏覽器請求一下,然后用開發(fā)者工具查看請求頭復(fù)制出來嘛。然后我們就好操作了,直接更改這一段字符串中最后的那個(gè)版本號(hào)標(biāo)識(shí)就好啦。 截圖中的這個(gè)版本號(hào),返回的結(jié)果是 ",1," 這樣的內(nèi)容。而如果我們改成 600.1.15 ,結(jié)果就會(huì)變成 "1,," 這樣。 接著,我們可以打開上面代碼中 if 代碼段內(nèi)的注釋,如果判定為 舊式 瀏覽器,那么就直接 return 進(jìn)行 301 跳轉(zhuǎn)到最開始的 indextest 目錄,并打開 1.txt 文件。這就是模擬我們可能會(huì)對一某些瀏覽器有一些特殊的操作。如果判定不是 舊式 瀏覽器的話,還是正常返回那三個(gè)變量的值。這就是變量在 Nginx 編程中的重要作用。 這個(gè) if 是不是很像我們的編程語法呀?但其實(shí),它也是個(gè)配置指令,或者你可以將整個(gè) Nginx 中的配置指令都看成是一種編程語言的語法。就像 HTML 是超文本標(biāo)記語言一樣,Nginx 的配置指令可以說也是構(gòu)建在主體的 C/C++ 程序之上的一套配置標(biāo)記語言。關(guān)于 if 更詳細(xì)的內(nèi)容,在后面的重寫模塊中會(huì)再詳細(xì)的學(xué)習(xí)。 最后上面那個(gè) ancient_browser_value 注釋大家也可以打開試下,不出意外的話,現(xiàn)在你怎么修改版本號(hào),怎么配其它的指令,一直都會(huì)是 ",0," 這樣的返回結(jié)果。 總結(jié)沒騙大家吧?index 和 charset 肯定是大家比較常見的配置指令。而且是非常常見,index 在默認(rèn)的配置文件中就有,而 charset 雖然沒有直接給出,但在默認(rèn)配置文件的注釋中也能看到,這就說明它也真的是非常常用的一種配置指令。另外就是 好了,繼續(xù)接下來的學(xué)習(xí)吧,這樣刷文檔的感覺咋樣?反正我現(xiàn)在發(fā)現(xiàn)官方文檔真的是我們的第一學(xué)習(xí)神器哦! 參考文檔: http:///en/docs/http/ngx_http_index_module.html http:///en/docs/http/ngx_http_autoindex_module.html http:///en/docs/http/ngx_http_charset_module.html http:///en/docs/http/ngx_http_browser_module.html |
|