Nginx、PCRE和中文URL(UTF8編碼)rewrite路徑重寫匹配問題

最近遇到了使用Nginx 重寫中文UTF8編碼路徑的問題。 才發現默認情況下Nginx的rewrite是不支持UTF8匹配的。 比如:

rewrite ^/(..)$ /2個字符文章.html break; #用2個點
可以匹配到 /ab 或 /51, 但 /漢字 是匹配不到的。 我測試了一下, 要匹配兩個字的 /漢字 路徑, 得用

rewrite ^/(……)$ /2個漢字文章.html break; #要用六個點

如果要讓 ^/(..)$ 匹配到2個漢字字符,得開啟Nginx對UTF8字符的正則支持, 準確點說是開啟Nginx使用的PCRE庫的對UTF8字符的支持。因為Nginx的rewrite模塊是調用PCRE來處理正則的。 如果PCRE沒有問題,Nginx支持UTF8編碼的重寫樣式是:

rewrite "(*UTF8)^/(..)$" /2個字符文章.html break;
#注意(*UTF8)前綴和引號的加入。

因為PCRE只有7.9以上的版本才支持這個(*UTF8)開頭,所以系統上的PCRE一定要使用7.9以上的版本。 另外,編譯PCRE時一定要開啟UTF8的支持。 即使用(–enable-utf8)參數。 檢查系統的PCRE版本和是否支持UTF8編碼可以使用
pcretest -C
命令。執行後會顯示如下的報告:

PCRE version 8.13 2011-08-16
Compiled with
UTF-8 support
Unicode properties support
Newline sequence is LF
R matches all Unicode newlines
Internal link size = 2
POSIX malloc threshold = 10
Default match limit = 10000000
Default recursion depth limit = 10000000
Match recursion uses stack

顯示“UTF-8 support”就是支持UTF8編碼了。

如果Nginx調用的PCRE為7.9以下的版本,使用 rewrite “(*UTF8)^/(..)$” /2個字符文章.html break; 這種形式的重寫,在執行nginx -t檢查時會出現如下的錯誤提示:

[emerg]: pcre_compile() failed: (*VERB) not recognized in “(*UTF8)^、……

如果Nginx調用的是7.9以上版本的PCRE,但是PCRE安裝時沒打開UTF8的支持開關,則會出現如下的錯誤提示:

nginx: [emerg] pcre_compile() failed: this version of PCRE is not compiled with PCRE_UTF8 support in “(*UTF8)^/…

解決辦法是安裝最新版本的的PCRE,並打開UTF8支持,方法如下(以當前8.13版的PCRE為例):
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.13.tar.gz
tar zxvf pcre-8.13.tar.gz
cd pcre-8.13
./configure --enable-utf8 --enable-unicode-properties
make
make install

然後重新編譯安裝Nginx。 Nginx默認會打開rewrite模塊,並會自動查找系統上已經安裝了的PCRE。 如果Nginx查找不到已經安裝在系統上的PCRE, 或者系統上有多個PCRE, nginx調用了不支持UTF8的、或低版本的PCRE時(我遇到了後一種情況,並花費了很長的時間解決這個問題,這也是我為什麼寫這篇總結文章在這裡給大家分享的原因。。。),可以在編譯安裝Nginx時指定PCRE源文件。例如:

wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.13.tar.gz
tar zxvf pcre-8.13.tar.gz
wget http://nginx.org/download/nginx-1.0.8.tar.gz
tar zxvf nginx-1.0.8.tar.gz
cd nginx-1.0.8
./configure
--with-pcre=../pcre-8.13

注意,如果接着直接make && make install的話, PCRE因為沒有啟用UTF8, nginx將不能支持UTF8重寫, 所以在這一種,我動了一點小手腳:打開./objs/Makefile 文件,找到以下段落:

../pcre-8.13/Makefile: objs/Makefile
cd ../pcre-8.13
&& if [ -f Makefile ]; then $(MAKE) distclean; fi
&& CC="$(CC)" CFLAGS="-O2 -fomit-frame-pointer -pipe "
./configure --disable-shared

在–disable-shared後加上 –enable-utf8和 –enable-unicode-properties參數, 即變成:
../pcre-8.13/Makefile: objs/Makefile
cd ../pcre-8.13
&& if [ -f Makefile ]; then $(MAKE) distclean; fi
&& CC="$(CC)" CFLAGS="-O2 -fomit-frame-pointer -pipe "
./configure --disable-shared --enable-utf8 --enable-unicode-properties

然後再make, make install。 最後關閉nginx並重啟nginx(這裡不能用nginx -s reload)。這樣nginx就支持中文UTF8編碼的url重寫了。

此條目發表在 信息處理, 站長文檔 分類目錄,貼了 , , , , , , , , , , , , , 標籤。將固定鏈接加入收藏夾。

Nginx、PCRE和中文URL(UTF8編碼)rewrite路徑重寫匹配問題》有 2 條評論

  1. 同樣也遇到了這個問題… md nginx的log,幾百M都是這個錯誤.謝謝分享解決方案了

  2. Pingback 引用通告: 再談Nginx Rewrite, 中文URL和其它 | 船長日誌

發表評論

電子郵件地址不會被公開。 必填項已用 * 標註

*

您可以使用這些 HTML 標籤和屬性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>