LiveBook 是 elixir 团队新推出的一款应用,可以使用它很方便地在浏览器中编写文章,并且在其中运行 elixir 代码。
我很好奇能否使用 LiveBook 直接更改当前服务器的路由配置,使得我们可以实现实时部署服务。比如我们在 LiveBook 里写好一个页面,然后直接配置到某个 url 路径上,别人就可以访问到。这样感觉非常酷,省去了繁琐的配置打包和发布的流程,而且从理论上是完全可以实现的。
说干就干,首先我在 fly.io 上部署了一个免费的 livebook 实例,你也可以在本地部署,很方便的。
启动之后在左侧的配置按钮里选择 Runtime settings
,选则 Embedded
。即在 livebook 本身的 erlang node 里执行代码。livebook 为了保证安全性和隔离性,默认是会另启动一个 node 来执行代码的,也就是 Elixir standalone
选项,但这样我们是无法修改路由配置的。
修改好之后,我新建了一个文档,就可以开始写代码了。Livebook 使用的是 Phoenix 框架,其底层的 HTTP 服务器是 Cowboy,再底层是 ranch。所以我们先通过 :ranch.info()
来获取当前服务器的一些信息。从返回值里我们知道了当前的 ranch server 的ref是 LivebookWeb.Endpoint.HTTP
,所有的路由(或者叫分发 Dispatch) 配置都是在这里面保存。下一步我们就可以对 dispatch 配置进行修改。
每个http请求都会被分发到不同的 handler(这个怎么翻译来着,抓手?),所以我们首先需要写一个用于测试的 handler。
defmodule TestHandler do
@behaviour :cowboy_handler
def init(req, state) do
req = :cowboy_req.reply(200, %{
\"content-type\" => \"text/plain\"
}, \"Hello World!\", req)
{:ok, req, state}
end
end
它的功能非常简单,无论收到什么都返回你好世界。接下来将它配置到我们的 dispatch 里面,注意要保留之前的 dispatch 内容,否则我们的 livebook 就访问不了了哈哈。
dispatch = :cowboy_router.compile([{:_, [], [
{\'/test\', [], TestHandler, %{}},
{:_, [], Phoenix.Endpoint.Cowboy2Handler, {LivebookWeb.Endpoint, []}}
]}])
最后使用 cowboy 提供的实时更新功能,将新的配置部署到我们的 ranch server 里面:
:cowboy.set_env(LivebookWeb.Endpoint.HTTP, :dispatch, dispatch)