路由机制

配置链接URL到Erlang模块(处理对应请求的模块)的映射就是路由。

当 Cowboy接收到一个请求时,它会尝试在给定的分发规则中匹配 域名 到对应的资源路径。如果匹配成功,那么对应的Erlang 模块就会被执行。

Cowboy首先会匹配域名,接着尝试找到匹配的资源路径。

Cowboy会将路由规则编译后,再使用。

结构

通用的路由结构是这样定义的: Routes= [Host1, Host2, ... HostN].

每一个域名的匹配规则 包含了 对连接路径的选项约束和路径部件的列表。

Host1= {HostMatch, PathsList}. Host2= {HostMatch, Constraints, PathsList}.

路径部件的定义如下: PathsList= [Path1, Path2, ... PathN].

最后,每一路径包含了该路径自身的匹配规则以及对应的处理模块 Path1= {PathMatch, Handler, Opts}. Path2= {PathMatch, Constraints, Handler, Opts}.

匹配规则语法

匹配语法规则用于标识 域名到路径间的处理handlers。 域名的语法规则: HostMatch1= "cowboy.example.org". HostMatch2= "cowboy.example.org.". HostMatch3= ".cowboy.example.org".

路径的语法规则: PathMatch= "/hats/:name/prices". HostMatch= ":subdomain.example.org".

此外,还可以将域名的某一字段保存到Req对象中,再后续可以使用,这就是值绑定。 PathMatch= "/hats/:name/prices". HostMatch= ":subdomain.example.org". 比如,http://test.example.org/hats/wild_cowboy_legendary/prices 将会 把test绑定到subdomain,而wild_cowboy_legendary就会绑定到name,它们可以被cow_req:binding/{2,3}中检索,绑定的名字必须是一个atom ‘_’:表示匹配任何内容

约束

匹配域名和路径完成后,就会检测是否满足可选的约束,约束如下:

1
2
{Name, int}
{Name, function, fun ((Value) -> true | {true, NewValue} | false)}

int 约束将会检查 绑定的二进制串是一个int,或可被转化成一个int function约束,将会调用给定的约束函数并且返回结果,给定函数必须自己保证不会崩溃的。

为了保存Cowboy可以更高效地查找正确的handler模块,Cowboy会编译定义好的路由分发规则。 编译的方法是:cowboy_router:compile/1.

1
2
3
4
5
6
7
8
9
	Dispatch= cowboy_router:compile([
    %% {HostMatch, list({PathMatch, Handler, Opts})}
    {'_', [{'_', my_handler, []}]}
	]),
	%% Name, NbAcceptors, TransOpts, ProtoOpts
	cowboy:start_http(my_http_listener, 100,
   	[{port, 8080}],
   	[{env, [{dispatch, Dispatch}]}]
	).

如果定义好的路由分发规则有错误,cowboy_router:compile/1 将会返回{error, badarg}

在线更新路由规则

通过 cowboy:set_env/3更新路由的分发规则,连接监听模块接受新的连接时就会使用新的路由分发规则。

1
2
    cowboy:set_env(my_http_listener, dispatch,
    cowboy_router:compile(Dispatch)).