環境:
centos6/7,nginx-1.9.15.
摘要說明:
上一篇主要講述nginx下的常用內置變量及if語句;
本章節主要講述nginx的如何配置跨域、緩存、壓縮;
步驟:
1.跨域
場景:首先我們舉例看看什麼叫做跨域:
當我們加載static.xxxx.com的頁面之後,在js中調用www.xxxx.com接口,這個時候就叫做跨域;因爲請求的主體已發生改變,瀏覽器拒絕執行;
解決方案:
其中解決跨域問題常用的編程方式就是jsonp;
而服務器端解決方式就是cors解決方案:
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。 它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求, 從而克服AJAX只能同源使用的限制。
簡單請求: 瀏覽器在跨源AJAX請求的頭信息之中,自動在添加一個Origin字段(本次請求來自哪個源 )。 服務器根據這個值,在許可範圍內,則在頭信息包含 Access-Control-Allow-Origin 。
複雜請求: 會在正式通信之前,增加一次HTTP查詢請求,稱爲"預檢"請求OPTIONS
實踐:
首先我們寫一個html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="jquery-1.11.2.js" ></script>
<script>
$(function(){
$.ajax({
async : false,
type : "POST",
url : "http://cccc1.study.xxxx.cn:2012/cccc/test1.do",
data : null,
dataType : 'json',
success : function(data) {
console.log(data)
}
});
});
</script>
</head>
<body>
<img src="http://cccc1.study.xxxx.cn:2012/test/page1.jpg" />
</body>
</html>
此時nginx配置:
server {
listen 2012;
server_name localhost;
location / {
root html;
}
location = /cccc/test1.do {
proxy_pass http://127.0.0.1:8888/cccc/test1.do;
}
error_page 500 502 503 504 /50x.html;
location /50x.html {
root html;
}
}
訪問頁面:http://cccc.study.xxxx:2012/test/page1.html
由於頁面的域名和ajax請求的域名不一致所以瀏覽器報跨域異常:
下面就是nginx的cors配置:
server {
listen 2012;
server_name localhost;
#判斷請求域名是否是指定域名的子域名,如果是,則將內置域名賦值給內置變量$allow_url,便於指定Access-Control-Allow-Origin
if ( $http_origin ~ http://(.*).xxxx){
set $allow_url $http_origin;
}
#是否允許請求帶有驗證信息
add_header Access-Control-Allow-Credentials true;
#允許跨域訪問的域名,可以是一個域的列表,也可以是通配符*
add_header Access-Control-Allow-Origin $allow_url;
#允許腳本訪問的返回頭
add_header Access-Control-Allow-Headers 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp';
#允許使用的請求方法,以逗號隔開
add_header Access-Control-Allow-Methods 'POST,GET,OPTIONS,PUT,DELETE';
#允許自定義的頭部,以逗號隔開,大小寫不敏感
add_header Access-Control-Expose-Headers 'WWW-Authenticate,Server-Authorization';
#P3P支持跨域cookie操作
add_header P3P 'policyref="/w3c/p3p.xml", CP="NOI DSP PSAa OUR BUS IND ONL UNI COM NAV INT LOC"';
add_header test 1;
if ($request_method = 'OPTIONS') {
return 204;
}
location / {
root html;
}
location = /cccc/test1.do {
proxy_pass http://pro.baoyjr.com/cccc/test1.do;
}
error_page 500 502 503 504 /50x.html;
location /50x.html {
root html;
}
}
上述配置是判斷域名是指定域名的子域名,若是將子域名賦值給內置變量,傳遞到後續的Access-Control-Allow-Origin;
但Access-Control-Allow-Origin也可以指定全部即*,也可以指定多個即在前面添加多個if即可;
此時訪問頁面可正常訪問,我們可以看下下述請求信息:
整理下整個請求流程:
- 當chrome發現ajax請求的網址,與當前主域名不一致(跨域)時,會在請求header中追加值頁面主域名值,即:origin = http://cccc.study.xxxx.cn;
- nginx在接收到ajax請求時,會查看origin值,查看請求域名;此處使用正則來校驗,即:只要是xxxx.cn下的網址,都允許訪問;返回信息時,nginx追加header值:access-control-allow-origin = cccc.study.xxxx.com(回答瀏覽器,此域名可以訪問)
- chrome收到ajax返回值後,查看返回的header中access-control-allow-origin的值,發現其中的值是正是當前的頁面主域名,即允許訪問,於是執行ajax返回值內容。(ps:若此處access-control-allow-origin不存在,或者值不是此域名,chrome就拒絕執行返回值)
2.防盜鏈
場景:由於圖片鏈接可以跨域訪問,所以圖片鏈接往往被其他網站盜用,從而增加服務器負擔;
解決方案:nginx可以通過valid_referers配置進行防盜鏈配置:
valid_referers
語法:valid_referers [none|blocked|server_names] ...
默認值:none
使用字段:server, location
這個指令在referer頭的基礎上爲 $invalid_referer 變量賦值,其值爲0或1。
可以使用這個指令來實現防盜鏈功能,如果valid_referers列表中沒有Referer頭的值, $invalid_referer將被設置爲1(參照下列)。
server {
listen 2013;
server_name localhost;
location / {
root html;
}
#防盜鏈,校驗加載圖片來源是否是指定域名,圖片不可直接下載及展示
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
valid_referers *.xxxx.cn;
if ($invalid_referer) {
return 404;
}
root html;
}
error_page 500 502 503 504 /50x.html;
location /50x.html {
root html;
}
}
上述配置就可以達到除指定域名及其子域名下的頁面可以訪問上述格式圖片,其他全部返回404;直接訪問圖片也不可以;
3.緩存
場景:業務中一般存在頁面來回切換或加載同樣的素材,若每次相同素材加載都需要重新加載是很消耗流量和加重響應速度
解決方案:nginx通過expires配置緩存時間告知瀏覽器該素材可進行緩存並緩存多長時間;
expires
語法:expires [time|@time-of-day|epoch|max|off]
默認值:expires off
使用字段:http, server, location
這個指令控制是否在應答中標記一個過期時間,如果是,如何標記。
- ·off 將禁止修改頭部中的 Expires和Cache-Control字段。
- ·epoch 將Expires頭設置爲1 January, 1970 00:00:01 GMT。
- ·max 將Expires頭設置爲31 December 2037 23:59:59 GMT,將Cache-Control最大化到10 years。
- ·如果將指令設置爲一個不帶@標記的值,那麼過期時間將是應答時間的相對時間(如果這個時間在“modified”之前),或者是文件的修改時間(當"modified"存在,在版本0.7.0和0.6.32可用),並且可以指定一個負的時間,它將Cache-Control頭設置爲no-cache比較。
- ·如果指令的值被設置爲一個帶@標記的值,那麼將指定一個絕對的time-of-day過期時間,可以指定兩種格式分別爲Hh或Hh:Mm,其中H的大小範圍爲0到24,M的大小範圍爲0到59(在0.7.9和0.6.34可用)。
- 一個非負的時間值將Cache-Control頭設置爲 max-age = #,#將適當的換算爲秒數。
注意:expires僅僅適用於200, 204, 301, 302,和304應答
雖然上述的使用方式很多,經常使用的配置如下:
server {
listen 2014;
server_name localhost;
location / {
root html;
}
#告知瀏覽器緩存此文件並設置緩存時間
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 10s;#緩存2秒
#expires 2m;#緩存2分鐘
#expires 2h;#緩存2小時
#expires 2d;#緩存2天
root html;
}
error_page 500 502 503 504 /50x.html;
location /50x.html {
root html;
}
}
通過測試我們可以看到二次訪問加載時間爲0秒;響應上顯示緩存時間爲10秒,達到要求
4、壓縮
場景:一些項目靜態資源如html、css、js等都很多且很大,請求起來很費時間及流量,但這些資源往往都可以進行壓縮,並且壓縮比例很大;
解決方案:nginx使用gzip可指定類型進行壓縮
gzip
語法:gzip on|off
默認值:gzip off
使用字段:http, server, location, location中的if字段
指定是否啓用gzip壓縮。
經常搭配下面使用:
- gzip_types:默認值爲gzip_types text/html ;爲除“text/html”之外的MIME類型啓用壓縮,“text/html”總是會被壓縮。
- gzip_min_length:默認值爲gzip_min_length 0 ;設置被壓縮的最小請求,單位爲bytes。少於這個值大小的請求將不會被壓縮,這個值由請求頭中的Content-Length字段決定。
- gzip_buffers :默認值爲gzip_buffers 4 4k/8k ;指定緩存壓縮應答的緩衝區數量和大小,如果不設置,一個緩存區的大小爲分頁大小,根據環境的不同可能是4k或8k。
- gzip_comp_level :默認值爲gzip_comp_level 1 ;指定壓縮等級,其值從1到9,1爲最小化壓縮(處理速度快),9爲最大化壓縮(處理速度慢)。
實例如下:
server {
listen 2015;
server_name localhost;
location / {
# 對js、css、html格式的文件啓用gzip壓縮功能,圖片格式由於壓縮比例太小,且壓縮耗費cpu不建議壓縮
gzip on; # 啓用gzip壓縮,默認是off,不啓用
gzip_types application/javascript text/css;#爲除“text/html”之外的MIME類型啓用壓縮,“text/html”總是會被壓縮。
gzip_min_length 1024; # 所壓縮文件的最小值,小於這個的不會壓縮
gzip_buffers 4 1k; # 設置壓縮響應的緩衝塊的大小和個數,默認是內存一個頁的大小
gzip_comp_level 1; # 壓縮水平,默認1。取值範圍1-9,取值越大壓縮比率越大,但越耗cpu時間
root html;
}
error_page 500 502 503 504 /50x.html;
location /50x.html {
root html;
}
}
通過測試:js能夠達到很好的壓縮
總結:由於圖片壓縮率不高,如果進行壓縮每次還要消耗資源如cpu等,得不償失,不建議壓縮圖片;