ちょっと

REST API で操作出来たら便利になりそうだなあと思った部分があったので、maru で実装してみようと思って、Maru ドキュメントの Basic Usage を写経してみたメモです。

◯ (Maru)

maru - Elixir RESTful Framework

github.com

先日の fukuoka.ex で教えて頂きました。

www.slideshare.net

特徴については、上記資料の 6 ページに簡潔に纏まっていますので転載させて頂きます。

有難うございます。
Ruby の grape という REST API ライクな API を生成するフレームワークにインスパイヤされているらしい。grape 自体初耳でした。

Basic Usage 写経

写経した環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1421

$ iex -v
Erlang/OTP 19 [erts-8.3]  [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

IEx 1.4.4

新規アプリケーションの作成

$ mix new oreno_app

以下のように出力されます。

$ mix new oreno_app
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/oreno_app.ex
* creating test
* creating test/test_helper.exs
* creating test/oreno_app_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd oreno_app
    mix test

Run "mix help" for more commands.

mix.exs に依存するモジュール名を定義

mix.exs に以下を追記する。

defp deps do
  [ {:maru, "~> 0.11"} ]
end

アプリケーションの実装

lib/oreno_app.ex に以下のように実装します。

defmodule OrenoApp.Router.Homepage do
  use Maru.Router

  get do
    json(conn, %{ hello: :maru })
  end
end

defmodule OrenoApp.API do
  use Maru.Router

  plug Plug.Parsers,
    pass: ["*/*"],
    json_decoder: Poison,
    parsers: [:urlencoded, :json, :multipart]
  
  mount OrenoApp.Router.Homepage

  rescue_from :all do
    conn
    |> put_status(500)
    |> text("Server Error")
  end
end

アプリケーションを起動させる為の設定

config/config.exs に以下を追記します。

config :maru, OrenoApp.API,
  http: [ip: {0, 0, 0, 0}, port: 8881]

ip: {0, 0, 0, 0} を追加しない場合、デフォルトでは 127.0.0.1 でのみ Listen するので Docker で動かす場合等は注意しませう。

アプリケーションの起動

依存するモジュールの導入 (maru の導入)

$ mix deps.get

以下のように出力されます。

$ mix deps.get
Running dependency resolution...
Dependency resolution completed:
  cowboy 1.1.2
  cowlib 1.0.2
  maru 0.11.4
  mime 1.1.0
  plug 1.3.5
  poison 3.1.0
  ranch 1.3.2
* Getting maru (Hex package)
  Checking package (https://repo.hex.pm/tarballs/maru-0.11.4.tar)
...

サーバーの起動

$ iex -S mix

以下のように出力され、コンパイルが走ります。

$ iex -S mix
Erlang/OTP 19 [erts-8.3]  [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

==> poison
Compiling 4 files (.ex)
Generated poison app
===> Compiling cowlib
src/cow_multipart.erl:392: Warning: crypto:rand_bytes/1 is deprecated and will be removed in a future release; use crypto:strong_rand_bytes/1
...

09:40:54.442 [info]  Starting Elixir.OrenoApp.API with Cowboy on http://0.0.0.0:8881
Interactive Elixir (1.4.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

Cowboy という Web サーバーが起動します。

Hello Maru

Web サーバーが起動したら API にアクセスしてみる。

$ curl http://127.0.0.1:8881 -w '\n' -i
HTTP/1.1 200 OK
server: Cowboy
date: Sat, 17 Jun 2017 01:02:15 GMT
content-length: 16
cache-control: max-age=0, private, must-revalidate
content-type: application/json; charset=utf-8

{"hello":"maru"}

やったー。

Basic Usage + アルファ

プラスアルファ

  • Docker で動かしたい

Dockerfile

mix deps.get 等がそのまま利用出来ないので焦ったものの、以下のような Dockerfile で一通り動かせることを確認しました。

ROM elixir
ADD ./ /app
WORKDIR /app
RUN mix local.hex --force && mix deps.get
EXPOSE 8881
CMD ["mix", "run", "--no-halt"]

あと、フォアグラウンドで Web サーバーを動かす方法についても悩みましたが、mix run --no-halt でいけるようです。

docker-compose.yml

version: '2'

services:
  hello_maru:
    build: ./
    volumes:
      - ./:/app
    ports:
      - "8881:8881"

Docker 環境でも Hello Maru

ビルドして…

$ docker-compose build
Building hello_maru
Step 1/6 : FROM elixir
 ---> 066128183b87
Step 2/6 : ADD ./ /app
 ---> f5e8affa64c7
Removing intermediate container 6cde27f8f51f
Step 3/6 : WORKDIR /app
 ---> 9c269ced9d4f

...

Removing intermediate container 01de153aa0ac
Successfully built 8cadb37872f7

Run すると…

$ docker-compose up -d
Creating network "orenoapp_default" with the default driver
Creating orenoapp_hello_maru_1

$ docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                                            NAMES
0ecfa2a6d96b        orenoapp_hello_maru       "mix run --no-halt"      11 seconds ago      Up 9 seconds        0.0.0.0:8881->8881/tcp                           orenoapp_hello_maru_1

Hello Maru.

$ curl http://127.0.0.1:8881 -w '\n' -i
HTTP/1.1 200 OK
server: Cowboy
date: Sat, 17 Jun 2017 01:02:45 GMT
content-length: 16
cache-control: max-age=0, private, must-revalidate
content-type: application/json; charset=utf-8

{"hello":"maru"}

本当に

丸っと 10 分くらいで Maru を体験することが出来ました。
こちらの写経については、進捗が芳しくありません。ボチボチやっていきます。

元記事はこちら

Elixir と Maru を使って REST API アプリケーションを丸っと 10 分くらいで実装する(写経する)