為了實現(xiàn)跳轉(zhuǎn)OSS和縮略圖的功能,我們需要使用nginx的一些功能來實現(xiàn)。
- location
- rewrite
- if指令
- 變量
- image_filter
1. location
Nginx中的location 指令是NginxHttpCoreModule中重要的指令。location 指令,是用來匹配URI進行配置,URI 即語法中的 "/uri " , 可以是字符串或正則表達式。如果使用正則表達式,則必須制定前綴。
__ Location語法語法:location [=|||^~] /uri/ { … } __
語法解釋:
= 開頭表示精確匹配
/和^~ 開頭表示常規(guī)字符串
~ 開頭表示區(qū)分大小寫的正則匹配
~* 開頭表示不區(qū)分大小寫的正則匹配
!~ 和 !~ 分別為區(qū)分大小寫不匹配及不區(qū)分大小寫不匹配 的正則
示例:
location = / {
# 只匹配"/".
[ configuration A ]
}
location / {
# 匹配任何請求,因為所有請求都是以"/"開始
# 但是更長字符匹配或者正則表達式匹配會優(yōu)先匹配
[ configuration B ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 開始的請求,并停止匹配 其它location
[ configuration C ]
}
location ~* .(gif|jpg|jpeg)$ {
# 匹配以 gif, jpg, or jpeg結(jié)尾的請求.
# 但是所有 /images/ 目錄的請求將由 [Configuration C]處理.
[ configuration D ]
}
2.rewrite
rewrite功能就是,使用nginx提供的全局變量或自己設(shè)置的變量,結(jié)合正則表達式和標(biāo)志位實現(xiàn)url重寫以及重定向。rewrite只能放在server{},location{},if{}中,并且只能對域名后邊的除去傳遞的參數(shù)外的字符串起作用,例如http://seanlook.com/a/we/index.php?id=1&u=str 只對/a/we/index.php重寫。
如果相對域名或參數(shù)字符串起作用,可以使用全局變量匹配,也可以使用proxy_pass反向代理。
表明看rewrite和location功能有點像,都能實現(xiàn)跳轉(zhuǎn),主要區(qū)別在于rewrite是在同一域名內(nèi)更改獲取資源的路徑,而location是對一類路徑做控制訪問或反向代理,可以proxy_pass到其他機器。很多情況下rewrite也會寫在location里,它們的執(zhí)行順序是:
- 執(zhí)行server塊的rewrite指令
- 執(zhí)行l(wèi)ocation匹配
- 執(zhí)行選定的location中的rewrite指令
如果其中某步URI被重寫,則重新循環(huán)執(zhí)行1-3,直到找到真實存在的文件;循環(huán)超過10次,則返回500 Internal Server Error錯誤。
__語法rewrite regex replacement [flag]; __
flag標(biāo)志位
- last :相當(dāng)于Apache的[L]標(biāo)記,表示完成rewrite
- break : 停止執(zhí)行當(dāng)前虛擬主機的后續(xù)rewrite指令集
- redirect : 返回302臨時重定向,地址欄會顯示跳轉(zhuǎn)后的地址
- permanent : 返回301永久重定向,地址欄會顯示跳轉(zhuǎn)后的地址
因為301和302不能簡單的只返回狀態(tài)碼,還必須有重定向的URL,這就是return指令無法返回301,302的原因了。這里 last 和 break 區(qū)別:
- last一般寫在server和if中,而break一般使用在location中
- last不終止重寫后的url匹配,即新的url會再從server走一遍匹配流程,而break終止重寫后的匹配
- break和last都能組織繼續(xù)執(zhí)行后面的rewrite指令
3.if指令
if判斷指令
語法為if(condition){...},對給定的條件condition進行判斷。如果為真,大括號內(nèi)的rewrite指令將被執(zhí)行,if條件(conditon)可以是如下任何內(nèi)容:
當(dāng)表達式只是一個變量時,如果值為空或任何以0開頭的字符串都會當(dāng)做false
直接比較變量和內(nèi)容時,使用=或!=
~正則表達式匹配,~*不區(qū)分大小寫的匹配,!~區(qū)分大小寫的不匹配
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執(zhí)行
例如:
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite請求到/msid/目錄下
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} //如果cookie匹配正則,設(shè)置變量$id等于正則引用部分
if ($request_method = POST) {
return 405;
} //如果提交方法為POST,則返回狀態(tài)405(Method not allowed)。return不能返回301,302
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通過 set 指令設(shè)置
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果請求的文件名不存在,則反向代理到localhost 。這里的break也是停止rewrite檢查
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.com www.leizhenfang.com;
if ($invalid_referer) {
return 404;
} //防盜鏈
}
4.變量
全局變量
下面是可以用作if判斷的全局變量
$args : 這個變量等于請求行中的參數(shù),同$query_string
$content_length : 請求頭中的Content-length字段。
$content_type : 請求頭中的Content-Type字段。
$document_root : 當(dāng)前請求在root指令中指定的值。
$host : 請求主機頭字段,否則為服務(wù)器名稱。
$http_user_agent : 客戶端agent信息
$http_cookie : 客戶端cookie信息
$limit_rate : 這個變量可以限制連接速率。
$request_method : 客戶端請求的動作,通常為GET或POST。
$remote_addr : 客戶端的IP地址。
$remote_port : 客戶端的端口。
$remote_user : 已經(jīng)經(jīng)過Auth Basic Module驗證的用戶名。
$request_filename : 當(dāng)前請求的文件路徑,由root或alias指令與URI請求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 請求使用的協(xié)議,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服務(wù)器地址,在完成一次系統(tǒng)調(diào)用后可以確定這個值。
$server_name : 服務(wù)器名稱。
$server_port : 請求到達服務(wù)器的端口號。
$request_uri : 包含請求參數(shù)的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。
$uri : 不帶請求參數(shù)的當(dāng)前URI,$uri不包含主機名,如”/foo/bar.html”。
$document_uri : 與$uri相同。
自定義變量
我們可以在 nginx.conf 文件中有下面這一行配置:
set $a "hello world";
我們使用了標(biāo)準(zhǔn) ngx_rewrite 模塊的 set 配置指令對變量 $a 進行了賦值操作.我們把字符串 hello world 賦給了它。
另一種以arg_開頭的所有變量,這個變量的值是當(dāng)前請求名為 name 的 URI 參數(shù)的值,而且還是未解碼的原始形式的值。
我們來看一個比較完整的示例:
location /test {
echo "name: $arg_name";
echo "class: $arg_class";
}
然后在命令行上使用各種參數(shù)組合去請求這個 /test 接口:
$ curl 'http://localhost:8080/test'
name:
class:
$ curl 'http://localhost:8080/test?name=Tom&class=3'
name: Tom
class: 3
$ curl 'http://localhost:8080/test?name=hello%20world&class=9'
name: hello%20world
class: 9
5. image_filter
image_filter 是nginx提供的集成圖片處理模塊,就可以用它實時縮放圖片,旋轉(zhuǎn)圖片,驗證圖片有效性以及獲取圖片寬高以及圖片類型信息。
2 模塊說明
image_filter off 關(guān)閉模塊
image_filter test 確保圖片是jpeg gif png否則返415錯誤
image_filter size 100 100輸出有關(guān)圖像的縮放大小
image_filter rotate 90|180|270 旋轉(zhuǎn)指定度數(shù)的圖像,參數(shù)能夠包括變量,單獨或一起與resize crop一起使用。
image_filter resize width height 按比例降低圖像到指定大小,公降低一個能夠還有一個用"-"來表示,出錯415,參數(shù)值可包括變量,能夠與rotate一起使用,則兩個一起生效。
image_filter crop width height按比例降低圖像比較大的側(cè)面積和還有一側(cè)多余的載翦邊緣,其他和rotate一樣。沒太理解
image_filter_buffer 10M 設(shè)置讀取圖像緩沖的最大大小,超過則415錯誤。
image_filter_interlace on 假設(shè)啟用,終于的圖像將被交錯。對于JPEG,終于的圖像將在“漸進式JPEG”格式。
image_filter_jpeg_quality 95設(shè)置變換的JPEG圖像的期望質(zhì)量??山邮艿闹凳菑?到100的范圍內(nèi)。較小的值通常意味著既降低圖像質(zhì)量,降低數(shù)據(jù)傳輸,推薦的最大值為95。參數(shù)值能夠包括變量。
image_filter_sharpen 100添加了終于圖像的清晰度。銳度百分比能夠超過100。零值將禁用銳化。參數(shù)值能夠包括變量。
image_filter_transparency on定義是否應(yīng)該透明轉(zhuǎn)換的GIF圖像或PNG圖像與調(diào)色板中指定的顏色時,能夠保留。透明度的損失將導(dǎo)致更好的圖像質(zhì)量。在PNG的Alpha通道總是保留透明度。
配置示例
location ~* /image/(.+)\.jpg$ {
root /data/;
access_log logs/test.access.log;
error_log logs/test.error.log;
set $width $arg_w;
set $height $arg_h;
set $function $arg_function;
set $file $1;
if ( $function = "" ) {
rewrite ^ http://192.168.0.121:8080/v1/AUTH_test/myfiles/$file.jpg permanent;
}
if ( $function = "image/resize" ) {
rewrite /(image)/(.+)\.jpg /v1/AUTH_test/myfiles/$file.jpg;
}
}
location ~* /v1/AUTH_test/myfiles/(.+)\.jpg {
proxy_pass http://192.168.0.121:8080;
set $width $arg_w;
set $height $arg_h;
image_filter resize $width $height;
image_filter_buffer 50M;
image_filter_jpeg_quality 95;
image_filter_transparency on;
}
當(dāng)訪問/image接口下面的圖片時,首先會判斷是否有function這個參數(shù),如果有,則跳轉(zhuǎn)訪問OSS存儲的圖片文件。如果沒有,則讀取變量參數(shù)arg_w, arg_h的值,進行圖片的縮放。

一個完整的數(shù)據(jù)分流和縮略圖配置就完成了
參考: