Gem 做了个使用前缀树的 router,可供 mruby 使用

cicholgricenchos · 发布于 2017年10月11日 · 最后由 jasl 回复于 2017年10月11日 · 531 次阅读
96

repo: https://github.com/CicholGricenchos/Mrouter

最近遇到用ngx_mruby匹配路由的需求,我们网站曾经有两三百条为了SEO做的url,大概是这个样子:

get 'office-supplies(.:format)' => 'catalog#category', :id => 2, :lang=>'en', :version => 'v1'
get 'computers-and-parts(.:format)' => 'catalog#category', :id => 3, :lang=>'en', :version => 'v1'
get 'accessories(.:format)' => 'catalog#category', :id => 4, :lang=>'en', :version => 'v1'
get 'office-supplies/:name(.:format)' => 'catalog#category', :id => 2, :lang=>'en', :version => 'v1'
get 'computers-and-parts/:name(.:format)' => 'catalog#category', :id => 3, :lang=>'en', :version => 'v1'

现在要做前后端分离的手机版,老板不想放弃这些链接,把这些都打包进js又会增加体积,干脆就在nginx上匹配了。

mruby目前还没有现成的router,看了一下mustermann,用了新语法不好移植。而且mustermann是用正则一行一行匹配,在我们这种用例可能动不动就要匹配三百多次,性能也不好。我觉得用前缀树做是比较合适的,以后可能还可以搞成dfa,所以就自己造了个轮子。

性能测试下来,匹配单行路由耗时是mustermann的9倍左右,但是当总路由数到几十以上,优势就比较明显了。有空的话改用c写应该更好一些。

虽然这个gem是为mruby搞的,但是ruby也是能用的,当然现在功能还很简单,有需要再加吧。。。

共收到 7 条回复
8

哇 用 ngx_mruby 啦

96
8hooopo 回复

是的,不得不用啊。。手机和pc一定要相同的url,就是读session也得用mruby了。。感觉很头疼

1107

没有考虑 (/page/:page)(/per_page/:per_page) 这种情况吧?我记得 Trie 这种不好做

96
1107jasl 回复

是指匹配不到 /per_page/34/page/12
这个可能得反过来加个定义,毕竟定义本身也没表达出可以反过来,别的应该还好吧

1107

这个要生成四条匹配

/page/:page
/per_page/:per_page
/
/page/:page/per_page/:per_page
96
1107jasl 回复

这些是可以的:

router = Mrouter.new
router.add_route '(/page/:page)(/per_page/:per_page)', '233'

p router.match '' # => {:tag=>"233"}
p router.match '/page' # => false
p router.match '/page/12' # => {:page=>"12", :tag=>"233"}
p router.match '/per_page/12' # => {:per_page=>"12", :tag=>"233"}
p router.match '/page/12/per_page/34' # => {:page=>"12", :per_page=>"34", :tag=>"233"}

我在遇到 ( 的时候直接让trie分叉了,然后匹配的时候是深度优先匹的。这样做可能trie重复的部分多一点,不过匹配是没问题的。

1107

那不错,之前我看过go的,这种情况没做处理

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册