複製鏈接
請複製以下鏈接發送給好友

AppConfig

鎖定
AppConfig服務是SAE為開發者提供的對web服務器進行自定義配置的功能。
中文名
AppConfig
類    型
服務功能
功    能
目錄默認頁面
提供者
SAE

AppConfig服務概要

使用AppConfig,開發者可以很方便的實現以下功能: [1] 
目錄默認頁面
自定義錯誤頁面
壓縮
頁面重定向
頁面過期
設置響應頭的content-type
設置頁面訪問權限
從上面的説明可以看出,AppConfig可以完全代替htaccess的常見功能,其實AppConfig正是SAE為了替代傳統apache htaccess而實現的功能,原因有兩點:
1、傳統htaccess效率不高,因為其針對所有目錄進行遞歸merge
2、傳統htaccess過於複雜,學習成本高。AppConfig具有效率高而且學習成本低的特點,AppConfig只在App訪問時針對根目錄生成一次規則,而且AppConfig採用類自然語言的規則描述,開發者只需要參考幾個簡單的例子即可熟悉使用。

AppConfigPHP使用指南

例子:
name: saetest
version: 1
編輯saetest/1/config.yaml,增加handle段,如:
name: saetest
version: 1
handle:
- rewrite: if(!is_dir() && !is_file()) goto "index.php?%{QUERY_STRING}"
編輯完成後,通過SVN代碼部署工具提交即可生效。或者你也可以通過在線代碼編輯器修改config.yaml
如果通過SVN部署,只需要在默認版本所在目錄下,如您的應用名為devapp,默認版本是3,那麼請在devapp/3/下創建config.yaml文 件,按下以下語法編寫,然後通過svn commit部署完成即可生效。
語法説明
AppConfig的語法分兩種,一種是簡單的參數羅列方式,一種是靈活的表達式語法,不同的功能會用到不同的類型的語法。

AppConfig參數方式

目錄默認頁面
- directoryindex: file_list
file_list 中各個文件名以空格分隔,directoryindex在 yaml 文件中僅有一項
例子:
- directoryindex: aaa.php bbb.html

AppConfig自定義錯誤頁面

- errordoc: httpcode error_file
httpcode是諸如404、302之類的http響應碼,error_file是服務器以httpcode響應請求時響應的文件。errordoc在yaml中可以配置多項。
- errordoc: 404 /path/404.html
- errordoc: 403 /path/403.html
表達式語法
其他功能需要用到表達式語法,其形式為:
if (expression) do_something
expression 有如下形式:
1) in_header["header_name"] op string_or_digit
2) out_header["header_name"] op string_or_digit
3) path op string
4) query_string op string
5) is_file()
6) is_dir()
關於以上形式説明如下:
1) in_header 是請求頭,out_header 是響應頭,header_name 是 header 的名字,具體的請求頭和響應頭參考RFC官方文檔
2) op 是操作符,有 ~(正則匹配) !~(正則不匹配) ==(相等,用於字符串和數字) !=(不相等,用於字符串和數字) >, >=, <, <=( 比較操作符僅用於整形數字)
3) string 是形如 "xxxx" 的字符串
4) string_or_digit 表示 string 或者 digit,根據 op 的種類,後面跟 string 或者 digit
5) path 是系統宏,表示用户請求的 url 去掉主機部分和查詢串後剩下的部分
6) query_string 是系統宏,表示查詢串,一般是url中問號後面的內容
7) is_file() 和 is_dir 是系統函數,判斷 path 是文件還是目錄,!is_file(),!is_dir() 分別是其否定形式。
表達式語法用於以下功能:

AppConfig壓縮

compress: if (single_express) compress
在 compress 中 single_express 表示單一的表達式,不能用 && 做複合,in_header,out_header,path 都可以出現在 single_ express 中
例如:
- compress: if(out_header["Content-Length"] >= 10240) compress
- compress: if(in_header["Referer"] == "gphone") compress
- compress: if(path ~ "/big/") compress
當頁面內容大於 10K字節時壓縮
- compress: if(out_header["Content-Length"] >= 10240) compress
當請求 header Content-Type 中包含 text 時壓縮
- compress: if(out_header["Content-Type"] ~ "text") compress
當響應 header Referer 等於 gphone 時壓縮
- compress: if(in_header["Referer"] == "gphone") compress
當請求的 url 包含“/big/” 時壓縮
- compress: if(path ~ "/big/") compress
注:對所有的壓縮,請求 header Accept-Encoding 包含 gzip,deflate 是題中之意。壓縮配置注意事項
通常情況,我們根據響應頭Content-length,判斷是否需要壓縮,例如:if(out_header["Content-Length"]>=10240) compress,這 個靜態頁面,如js,css,html都是沒有問題的。
但是對php腳本,響應header中沒有Content-length這個頭,它使用Transfer-Encoding: chunked,這個頭表示頁面輸出用chunked 編碼。此時要實現壓縮,可以通過配置appconfig,同時在php腳本中輸出相應頭的方式實現。
例如在appconfig中寫 if(out_header["Use-Compress"] == "1") compress,在需要壓縮的php腳本中寫

AppConfigURL重寫

- rewrite: if (complex_express) goto target_url
在 rewrite 中,complex_express 可以用 && 連接,組成複合表達式。除 out_header (沒辦法根據響應 header 做重定向) 外都可以 出現在 rewrite 的 if 中,並且 path 只能出現一個(如果有多個,只有最後一個生效,其它被忽略),當省略 path 時,表示任意請求。
target_url 表示重定向的目標url,在target_url 可以以 $N 的形式表示 path 中匹配到的內容,%N 的形式表示最後一個query_string 中 匹配到的內容,因為query_string 可以在 if 中出現多次,以%{QUERY_STRING} 表示查詢串。
例如:
- rewrite: if(query_string ~ "^(so)$" && path ~ "zhaochou$") goto "/url/%1"
- rewrite: if(is_dir( ) && path ~ "urldir/(.*)") goto "/url/$1"
- rewrite: if( !is_file() && !is_dir()) goto "index.php?%{QUERY_STRING}"
指過期時間和頭信息
- expire: if (single_express) time seconds
- mime: if (single_express) type content-type
seconds 是秒數,content-type 是表示文檔類型的字符串。
例如:
- expire: if(in_header["referer"] ~ "sina") time 10
- mime: if(path ~ "\.pdf2$") type "application/pdf"
設置響應header Content-Type
如果 url 請求文件的擴展名是 pdf2,設置 Content-Type 為 application/pdf
- mime: if(path ~ "\.pdf2$") type "application/pdf"
只要請求 header referer 包含字符串 sina,就設置 Content-Type 為 text/plain
- mime: if(in_header["referer"] ~ "sina") type "text/plain"
在 expire 和 mime 中 single_express 表示單一的表達式,不能用 && 複合,in_header,path 都可以出現在 single_express 中,並且 op 只能是 ~ 或者 ==,即只支持正則匹配和字符串比較。

AppConfig訪問控制

禁止127.0.0.1 訪問private目錄
- hostaccess: if(path ~ "/private/") deny "127.0.0.1"
只允許127.0.0.1 訪問.conf結尾的文件
- hostaccess: if(path ~ "\.conf$") allow "127.0.0.1"
禁止127.0.0.1 的所有訪問(這個要慎用)
- hostaccess: deny "127.0.0.1"
對cron任務保護,防止被外部抓取,我們將cron任務放在cron目錄下(sae中cron服務執行時,走的是內部網絡)
- hostaccess: if(path ~ "/cron/") allow "10.0.0.0/8" 允許10打頭的所有IP
對於屏蔽一組IP地址,可以寫成子網掩碼形式,或者將多個IP之間加以空格。子網掩碼形式如下:
- hostaccess: if(path ~ "/cron/") deny "108.192.8.0/24" 屏蔽108.192.8打頭的所有IP
多個IP形式如下:
- hostaccess: allow "108.134.13.24 108.122.122.13" 允許108.134.13.24和108.122.122.13這兩個IP
或:
- hostaccess: allow "108.134.13.24","108.122.122.13"
(ip地址需要加引號,all代表所有IP地址,具體可以參考Apache配置.allow是白名單方式,deny是黑名單)

AppConfig簡單的認證

訪問secret目錄需要密碼,允許用户test用密碼123qwe訪問,用户coder用密碼123asd訪問
- passwdaccess: if(path ~ "/secret/") passwd "test:123qwe coder:123asd"
訪問.text結尾的文件需要密碼,允許用户writer用密碼123zxc
- passwdaccess: if(path ~ "\.text$") passwd "writer:123zxc"
所有訪問都要密碼,允許用户writer用密碼123zxc訪問
- passwdaccess: passwd "write:123zxc"
用户的網站後台程序都放在admin目錄下,需要對admin目錄做密碼保護
- passwdaccess: if(path ~ "/admin/") passwd "admin:admin123"
在 hostaccess 和 passwdaccess 中 single_express 表示單一的表達式,不能用 && 複合,in_header,path 都可以出現在 single_ express 中,並且op 只能是 ~ 或者 ==,即只支持正則匹配和字符串比較,並且 if 語句可以省略,表示無條件執行訪問控制

AppConfig備註和説明

更多例子:
目錄默認頁面
當訪問url沒有指定文件時,返回aaa.php,如果其不存在,則返回bbb.html
- directoryindex: aaa.php bbb.html
自定義錯誤頁面
遇到 404 錯誤,返回 /path/404.html 文件。遇到 403 錯誤,返回 /path/404.html 文件
- errordoc: 404 /path/404.html
- errordoc: 403 /path/403.html

AppConfig壓縮生效檢查

檢查是不是輸出了響應頭:Content-Encoding: gzip。
IE下的HttpWatch和FireFox下的Firebug都可以查看頁面的響應header。

AppConfig頁面重定向

當 url 匹配 urldir/(.*) ,並且 輸入 header referer 等於 sina 時,跳轉至頁面 /usr/$1,$1 表示剛剛匹配的 urldir/(.*) 中的 (.*) 部分。
- rewrite: if (path ~ "urldir/(.*)" && in_header["referer"] == "sina") goto "/url/$1"
當 url 匹配 urldir/(.*),並且請求的是一個目錄時,跳轉至 /url/$1
- rewrite: if(is_dir( ) && path ~ "urldir/(.*)") goto "/url/$1"
當 url 匹配 path,並且請求的不是一個文件時,跳轉至 /url/query.php
- rewrite: if(! is_file() && path ~ "path") goto "/url/query.php"
當查詢串等於so,並且 url 以 zhaochou 結尾時,跳轉至 /url/%1,%1 表示 query_string 匹配到的部分。
- rewrite: if(query_string ~ "^(so)$" && path ~ "zhaochou$") goto "/url/%1"
查詢串不包含sohu,並且 url 以zhaochou結尾時,跳轉至/url/query.php?%{QUERY_STRING},%{QUERY_STRING}表示查詢串。
- rewrite: if(query_string !~ "sohu" && path ~ "zhaochou$") goto "/url/query.php?${QUERY_STRING}"
如果 url 既不是文件,也不是目錄,跳轉至 index.php?%{QUERY_STRING}
- rewrite: if( !is_file() && !is_dir()) goto "index.php?%{QUERY_STRING}"設置響應頭的mime類型
如果 url 請求文件的擴展名是 pdf2,設置 Content-Type 為 application/pdf
- mme: if(path ~ "\.pdf2$") type "application/pdf"
只要請求 header referer 包含字符串 sina,就設置 Content-Type 為 text/plain
- mime: if(in_header["referer"] ~ "sina") type "text/plain"

AppConfig頁面過期

如果請求 header Referer 包含 字符串sina,設置過期時間10s
- expire: if(in_header["referer"] ~ "sina") time 10
如果 url 以 lib\.js 結尾,設置過期時間100s
- expire: if(path ~ "lib\.js$") time 100

AppConfigFAQ

1、如果有形如 path ~ "^(.*)$" 類的請求,一定要加上 is_file 或 is_dir 之類的判斷,防止無窮的rewrite。
2、path 是用户請求的資源路徑,比如請求 http://localhost/b/index.php?a=4,那麼path就是 /b/index.php。
3、在goto語句中,雖然某些時候可以不以/開頭,但是強烈建議以/開頭。 生效檢查
檢查是不是輸出了響應頭:Cache-Control。IE下的HttpWatch和FireFox下的Firebug都可以查看頁面的響應header。

AppConfig配置工具

SAE已支持在應用管理平台對AppConfig進行配置.
參考資料