指定路由规则,路由到不同组件
Specify route rules, and route to different components
我知道如何使用 Mason::Plugin::RouterSimple 为页面组件指定路由,例如给定 url of:
/archives/2015/07
我可以这样创建组件 archives.mc
:
<%class>
route "{year:[0-9]{4}}/{month:[0-9]{2}}";
</%class>
Archives for the month of <% $.month %>/<% $.year %>
同样,我可以创建一个 news.mc
组件来处理 url 个:
/news/2012/04
这很好(而且非常优雅!)但现在我想要的是能够处理 url 如下所示:
/john/archives/2014/12
/john/news/2014/03
/peter/news/2015/09
/bill/archives/2012/06
等我知道我可以将路由规则写为:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
但是请求必须由两个不同的组件处理。如何将请求路由到不同的组件? archives.mc
和 news.mc
不会被 Mason 匹配,因为组件名称前有用户名。
问题是,虽然像 /archives/2014/12
这样的 urs 可以由 /archives.mc
组件轻松处理,但对于像 /john/archives/2014/12
和 /bill/archives/2012/06
这样的 url不清楚将存档组件放在哪里。
Mason 将尝试匹配以下组件(这是一个简化列表,请参阅 Mason::Manual::RequestDispatch):
...
/john/archives.{mp,mc}
/john/dhandler.{mp,mc}
/john.{mp,mc}
但最后...
/dhandler.{mp,mc}
所以我的想法是在根目录下放一个dhandler.mc
组件:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
<%init>
$m->comp($.action.'.mi', user=>$.user, year=>$.year, month=>$.month);
</%init>
如果url匹配第一条路由,它将调用archives.mi
组件:
<%class>
has 'user';
has 'year';
has 'month';
</%class>
<% $.user %>'s archives for the month of <% $.month %>/<% $.year %>
(我使用了 .mi
组件,因此它只能在内部访问)。
可以改进 dhandler(更好的正则表达式,可以从数据库中检查用户 table 并拒绝请求等)
由于我的档案和新闻组件可以接受 POST/GET 数据,并且由于我想接受任何数据,所以我可以通过以下方式传递所有内容:
$m->comp($._action.'.mi', %{$.args});
不是太优雅,但看起来它起作用了。
我知道如何使用 Mason::Plugin::RouterSimple 为页面组件指定路由,例如给定 url of:
/archives/2015/07
我可以这样创建组件 archives.mc
:
<%class>
route "{year:[0-9]{4}}/{month:[0-9]{2}}";
</%class>
Archives for the month of <% $.month %>/<% $.year %>
同样,我可以创建一个 news.mc
组件来处理 url 个:
/news/2012/04
这很好(而且非常优雅!)但现在我想要的是能够处理 url 如下所示:
/john/archives/2014/12
/john/news/2014/03
/peter/news/2015/09
/bill/archives/2012/06
等我知道我可以将路由规则写为:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
但是请求必须由两个不同的组件处理。如何将请求路由到不同的组件? archives.mc
和 news.mc
不会被 Mason 匹配,因为组件名称前有用户名。
问题是,虽然像 /archives/2014/12
这样的 urs 可以由 /archives.mc
组件轻松处理,但对于像 /john/archives/2014/12
和 /bill/archives/2012/06
这样的 url不清楚将存档组件放在哪里。
Mason 将尝试匹配以下组件(这是一个简化列表,请参阅 Mason::Manual::RequestDispatch):
...
/john/archives.{mp,mc}
/john/dhandler.{mp,mc}
/john.{mp,mc}
但最后...
/dhandler.{mp,mc}
所以我的想法是在根目录下放一个dhandler.mc
组件:
<%class>
route "{user:[a-z]+}/archives/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'archives' };
route "{user:[a-z]+}/news/{year:[0-9]{4}}/{month:[0-9]{2}}", { action=> 'news' };
</%class>
<%init>
$m->comp($.action.'.mi', user=>$.user, year=>$.year, month=>$.month);
</%init>
如果url匹配第一条路由,它将调用archives.mi
组件:
<%class>
has 'user';
has 'year';
has 'month';
</%class>
<% $.user %>'s archives for the month of <% $.month %>/<% $.year %>
(我使用了 .mi
组件,因此它只能在内部访问)。
可以改进 dhandler(更好的正则表达式,可以从数据库中检查用户 table 并拒绝请求等)
由于我的档案和新闻组件可以接受 POST/GET 数据,并且由于我想接受任何数据,所以我可以通过以下方式传递所有内容:
$m->comp($._action.'.mi', %{$.args});
不是太优雅,但看起来它起作用了。