ObjC/Swift 在 Swift 下实现了 Rails 风格的路由库
继续为Swift节点添砖加瓦...
项目地址:https://github.com/jasl/RouterX
最终下决定造这个轮子主要有几个动机:
- 一篇来自天猫团队的分享 解耦神器 —— 统跳协议和Rewrite引擎
- 之前帮公司的iOS团队设计过推送跳转指定到特定界面、从应用外部通过自定义Scheme跳转到应用内指定界面
- 最近刚刚为网站添加iOS Universal links 支持(大致原理是在网站根目录建立一个配置文件,访问指定域的所有URL都会自动跳转到应用,iOS会将用户访问的URL传递给应用)。
我发现这几个场景的需求都是一致的并且和我们熟知的Web框架中的路由层相似。
利用双休日分析了下C#的ASP.net MVC、PHP的Laravel、Symphony,Go的HttpRouter还有若干小型的Web框架和iOS的Router库,首先先给一个结论:
Rails是Web开发最强框架绝对不是偶然的,Journey(tenderlove为Rails设计的路由规则解析库)的原理是为路由设计了一门表达式语言(使用RACC定义),然后构造出AST进行匹配,没有任何一个语言的同类库把这个问题上升到如此高度去解决。
这并不是炫技,通过这个方式可以实现很多其他途径很难做到的功能并且保持在匹配时的高性能,比如:/articles/(/page/:page)(/sort/:sort)
这种双可选的情况,除了Rails没有任何一家可以支持。
另外,Journey可以把定义好的路由导出成状态迁移图,进行可视化浏览,在Rails Console下输入 File.write 'fsm.html', app._routes.router.visualizer
然后去项目目录打开 fsm.html
即可 tenderlove的示例
不过,Journey的Parser因为是用RACC生成的,Swift下没有类似工具,此外代码没有文档,写得也比较绕(我是没读懂...),所以 RouterX 是基于我的思路实现的,目前功能已经完成。
一个典型的复杂路由:/articles(/page/:page(/per_page/:per_page))(/sort/:sort)(.:format)
可以正确的生成AST匹配如下模式
/articles
/articles/sort/:sort
/articles/sort/:sort.:format
/articles/page/:page
/articles/page/:page/sort/:sort
/articles/page/:page/sort/:sort.:format
/articles/page/:page/per_page/:per_page
/articles/page/:page/per_page/:per_page/sort/:sort
/articles/page/:page/per_page/:per_page/sort/:sort.:format
/articles/page/:page/per_page/:per_page.:format
/articles/page/:page.:format
/articles.:format
也可以正确的进行匹配,主要代码都已经用单元测试覆盖好。
我没学过编译原理,之前有请教过 @luikore 大神一些问题,消化一下看看如何重构让代码质量和性能更好。
PS:对Rails的路由原理感兴趣的同学可以读一下 Journey into Rails Routing -- an under the hood look at how routing works Rex, Rexical and Rails routing 这两篇文章(这个Blog的文章都挺不错的),不过作者后来也是坑掉了...
Go的 HttpRouter 是利用Trie数据结构实现的,在README里有讲原理,比较有意思。