标题：AppConfig
服务概要
AppConfig服务是SAE为开发者提供的对web服务器进行自定义配置的功能。
使用AppConfig，开发者可以很方便的实现以下功能：[1]
目录默认页面
自定义错误页面
压缩
页面重定向
页面过期
设置响应头的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/") compressURL重写- 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 100FAQ: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进行配置.