知行社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1677|回复: 1
收起左侧

[空间域名] 新浪 sae AppConfig 服务

[复制链接]
本帖最后由 :-(相见易得好久 于 2012-1-6 17:13 编辑


服务概要

    AppConfig服务是SAE为开发者提供的对web服务器进行自定义配置的功能,使用AppConfig,开发者可以很方便的实现以下功能:
• 目录默认页面
• 自定义错误页面
• 压缩
• 页面重定向
• 页面过期
• 设置响应头的content-type
• 设置页面访问权限

    从上面的说明可以看出,AppConfig可以完全代替htaccess的常见功能,其实AppConfig正是SAE为了替代传统apache htaccess而实现的功能,原因有两点:

    1. 传统htaccess效率不高,因为其针对所有目录进行递归merge

    2. 传统htaccess过于复杂,学习成本高。AppConfig具有效率高而且学习成本低的特点,AppConfig只在App访问时针对根目录生成一次规则,而且AppConfig采用类自然语言的规则描述,开发者只需要参考几个简单的例子即可熟悉使用。



使用指南

设置

    例子:

    appname: 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/") allow "108.192.8.0/24" 屏蔽108.192.8打头的所有IP

   





    (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

    - mime: 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
 楼主| :-(相见易得好久 发表于 2012-1-6 17:08 | 显示全部楼层
压缩配置注意事项

通常情况,我们根据响应头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

- mime: 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://x.sinaapp.com/b/index.php?a=4,那么path就是 /b/index.php。

3. 在goto语句中,虽然某些时候可以不以/开头,但是强烈建议以/开头。

生效检查

检查是不是输出了响应头:Cache-Control。IE下的HttpWatch和FireFox下的Firebug都可以查看页面的响应header。

第三方工具

第三方开发的生成AppConfig的小工具 http://saetools.sinaapp.com/appconfig.html

QQ|小黑屋|手机版|知行技术社区 ( 湘ICP备11020288号-1 )

GMT+8, 2020-11-25 01:15 , Processed in 0.021052 second(s), 11 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表