其实Tornado对子域名和泛域名(除了特别说明外,以下子域名和泛域名均简称为泛域名)的支持并不是什么新鲜事,两年多前我用Tornado写的开源网站 http://poweredsites.org 就有了对泛域名的支持,但是Tornado的官方文档里并没有明确对此功能进行说明,虽然源代码里是有注释的,终是有点隐晦,这不,近日mywaiting同学就遇到了这个问题,我应邀特撰此博文,分享下我对此的一点点经验。
通常,用Tornado添加url映射路由表是直接传handlers给Application这种方式的,比如官方的chatdemo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
这种方式其实添加的是一个域名通配的url映射表,即域名&子域名不限,只要访问能够解析到这个chatdemo上,“/auth/login” “/auth/login”这些url就都能够正常运行。假设www.feilong.me、abc.feilong.me、feilong2.me这个三个(子)域名均配置为可由这个chatdemo程序来host,那么访问这三个(子)域名均可以正常使用这个chatdemo,总之域名是无关的。
实际上,这种方式它的内部是通过Application里的这个add_handlers来实现的(原码注释如下):
1 2 3 4 5 6 7 8 |
|
只不过它是隐式的调用这个add_handlers而已,其关键点就在于第一个参数host_pattern(匹配域名的)上,上面那种方式,默认添加的host_pattern是”.*$”,即域名通配,若要支持泛域名,只需要显式的调用add_handlers来添加相应的host_pattern和handlers即可。
接下来就以poweredsites的源码来介绍Tornado对泛域名的支持,app.py里的Application里面有这么几句:
1 2 3 4 5 6 |
|
常见的方式super(Application, self).__init__(handlers, **settings)添加的是根域名poweredsites的handlers,接着用for循环显式添加的是子域名和泛域名的handlers。这里的sub_handlers依次放有各子域名的handlers,其最后一个是泛域名的handlers:
1 2 3 4 5 |
|
指定的子域名的sub_handlers(site.sub_handlers)是这个样子的,这里的第一个元素就是host_pattern:
1 2 3 4 5 6 7 8 |
|
泛域名(project.sub_handlers)的区别也就在于这第一个元素,即用来做host_pattern的是通配一些子域名的:
1 2 3 4 5 6 |
|
在用到了泛域名的ProjectIndexHandler里,运行时具体的子域名就可以通过下面这样的方式获得:
1 2 3 |
|
需要说明的是,Tornado里面的url映射表和Django一样是有顺序的,即url依次序由上到下匹配,只要匹配到就立即结束,不再往下匹配,而带子域名和泛域名的url路由其匹配优先级是要高于通配域名”.*$”的(这个不用你操心,add_handlers会自动为你做到这一点)。同样的,对于泛域名,因为其子域名是通配的,因此指定子域名的handlers需要放到泛域名前添加,如admin、blog这类子域名的handlers要放在泛域名之前,这就是poweredsites里sub_handlers.append(project.sub_handlers)放到最后一条的原因,project这条是对应泛域名的,http://tornado.poweredsites.org 就是靠这一条来实现的。
备注:需要支持泛域名,首先要你的域名解析支持泛域名。
转载请注明出处:http://feilong.me/2012/08/wildcard-subdomain-support-in-tornado