Trot is an Elixir web micro-framework based on Plug and Cowboy.
TrotはPlugとCowboyで作られたマイクロWebフレームワークらしいです。
rubyのsinatraと同じようなことをelixirでもしたくなったので色々探した結果、trotというパッケージを見つけたのでその使い方を簡単に紹介します。
作る
準備
mix new trot_sample
今回はTrotSampleというプロジェクトをmixで作りました。
まずはmix.exsに依存関係を追加
def application do
[application: [:trot]]
end
defp deps do
[{:trot, github: "hexedpackets/trot"}]
end
設定と実装
READMEに書いてあるようにconfig/config.exsに追記します。
use Mix.Config
config :trot, :port, 4000
config :trot, :router, TrotSample
今回は最低限の設定で。
あとはメインとなるRouterを書いていきます。
defmodule TrotSample do
use Trot.Router
get "/ping" do
"pong"
end
get "double/:number" do
number |> String.to_integer |> (&(&1 * 2)).() |> Integer.to_string
end
post "/echo" do
{:ok, body, conn} = read_body conn
body
end
post "/hello" do
conn = fetch_query_params(conn)
"Hello, #{conn.params["name"]}!"
end
get "/json" do
%{lang: "elixir"}
end
end
上から順に
- 単純なGET
- URL中のパターンマッチ
- POSTのbodyを返す
- POSTのクエリパラメータを返す
- JSONの返却
をしています。
リクエストのbodyはread_body
、パラメータはfetch_query_params
を使う必要があるのですが、READMEには全く書いてなくてものすごく悩みました。結局Plugについて調べている最中に発見しました。
ところでパイプラインの途中で匿名関数を使うときに(&(&1 * 2)).()
や(fn x -> x * 2 end).()
と書かないといけないのはどうにかなりませんかね?
叩く
起動して叩いてみます
$ mix trot.server
$ curl http://localhost:4000/ping
pong
$ curl http://localhost:4000/double/10
20
$ curl -d "are you ok?" http://localhost:4000/echo
are you ok?
$ curl -d "" http://localhost:4000/hello?name=techno
Hello, techno!
$ curl http://localhost:4000/json
{"lang":"elixir"}
まだ試していませんがテンプレートをレンダリングすることもできるようです。
静的コンテンツ
static
の使い方に若干嵌ったので・・・
trotのソースではstatic
は以下のように定義されています。
@static_root Path.relative_to_cwd("priv/static")
~~
~~
defmacro static(at, from), do: static_plug(at, from)
defmacro static(at), do: static_plug(at, "/")
defp static_plug(at, from) do
quote do
path = Path.join(@static_root, unquote(from))
@plugs {Plug.Static, [at: unquote(at), from: path], true}
end
end
従って
def MyRouter do
static "/css", "assets"
end
と書くと、内部でPath.join(@static_root, "assets")
のようなコードがマクロによって生成されるので、静的コンテンツはpriv/static/assets/
以下に置く必要があります。そして、/css/~
というパスのリクエストによってコンテンツが返されます。
例えば/static
にファイルを置いて、/assets/~
というパスのリクエストによって静的コンテンツを返したい場合は
defmodule MyRouter do
@static_root "/"
static "/assets", "static"
end
あるいは
defmodule MyRouter do
@static_root "static"
static "/assets"
と書けば良いわけですね。
参考
hexedpackets/trot: An Elixir web micro-framework.
[Elixir+Trot] Trot-Frameworkを使って"Hello Trot!!"するだけの簡単なお仕事・・・
週刊Elixirライブラリ2015-3 - ハードリカーエンジニア