AppConfig服务是SAE为开发者提供的对web伺服器进行自定义配置的功能。
基本介绍
- 中文名:AppConfig
- 类型:服务功能
- 功能:目录默认页面
- 提供者:SAE
服务概要
使用AppConfig,开发者可以很方便的实现以下功能:
目录默认页面
自定义错误页面
压缩
页面重定向
页面过期
设定回响头的content-type
设定页面访问许可权
从上面的说明可以看出,AppConfig可以完全代替htaccess的常见功能,其实AppConfig正是SAE为了替代传统apache htaccess而实现的功能,原因有两点:
1、传统htaccess效率不高,因为其针对所有目录进行递归merge
2、传统htaccess过于複杂,学习成本高。AppConfig具有效率高而且学习成本低的特点,AppConfig只在App访问时针对根目录生成一次规则,而且AppConfig採用类自然语言的规则描述,开发者只需要参考几个简单的例子即可熟悉使用。
PHP使用指南
例子:
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的语法分两种,一种是简单的参数罗列方式,一种是灵活的表达式语法,不同的功能会用到不同的类型的语法。
参数方式
目录默认页面
- directoryindex: file_list
file_list 中各个档案名称以空格分隔,directoryindex在 yaml 档案中仅有一项
例子:
- directoryindex: aaa.php bbb.html
自定义错误页面
- 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() 分别是其否定形式。
表达式语法用于以下功能:
压缩
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
URL重写
- 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 只能是 ~ 或者 ==,即只支持正则匹配和字元串比较。
访问控制
禁止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是黑名单)
简单的认证
访问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 语句可以省略,表示无条件执行访问控制
备注和说明
更多例子:
目录默认页面
当访问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
压缩
当页面内容大于 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脚本中写
压缩生效检查
检查是不是输出了回响头:Content-Encoding: gzip。
IE下的HttpWatch和FireFox下的Firebug都可以查看页面的回响header。
页面重定向
当 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"
页面过期
如果请求 header Referer 包含 字元串sina,设定过期时间10s
- expire: if(in_header["referer"] ~ "sina") time 10
如果 url 以 lib\.js 结尾,设定过期时间100s
- expire: if(path ~ "lib\.js$") time 100
FAQ
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。
配置工具
SAE已支持在套用管理平台对AppConfig进行配置.