LoginSignup
10
3

More than 5 years have passed since last update.

mrubyでyamlを読みこんでh2oが返す

Posted at

h2oとmruby

ある日、

「h2oとmruby使ったらhtmlがなくてもresponse返せるんじゃないか?」

と思ったので、やってみることにしました。

mrubyでどのように返すデータを持つか

さて、responseの内容をmruby scriptの中にベタ書きするのはカッコ悪そうなので、yamlに記述して、外部から読みこむことにします。

h2oの用意

ひとまず、mrubyで簡単なresponseを返すh2oを用意します。

Dockerfile
FROM unasuke/h2o-alpine:v2.0.4

COPY . /etc/h2o
CMD ["h2o", "--mode=master", "-c", "h2o.conf"]
h2o.conf
listen: 80
hosts:
  "127.0.0.1:80":
    paths:
      "/":
        mruby.handler-file: server.rb
access-log: /dev/stdout
server.rb
class Server
  def call(env)
    [200,
     {
       "content-type" => "text/plain; charset=utf-8",
     },
     ["Hello mruby in h2o!"]
    ]
  end
end

Server.new

Create simple server · unasuke/mruby_ac2016@27cf7eb

# buildしてrun
% docker build -t h2o_mruby .
% docker run -it -p 8080:80 h2o_mruby

すると、このように8080番ポートでアクセスできるようになりました。mrubyがresponseを返しているのがわかります。
response from server.rb

mrubyがyamlを読みこむために

mruby scriptの中でyamlを読みこむためには、AndrewBelt/mruby-yamlを使う必要があります。が、このmrbgemは素のh2oには含まれていないので、mruby-yamlを含んだh2oをbuildしなくてはいけません。

そこで、そのようなh2oを用意しました。
unasuke/h2o at mruby-yaml

用意といっても簡単で、deps 以下にmruby-yamlをcloneしてくるだけです。

そして、Dockerfileを次のように変更して、h2oをbuildします。

Dockerfile
FROM alpine

RUN apk add --no-cache --virtual=builddeps \
        bison           \
        ca-certificates \
        cmake           \
        curl            \
        gcc             \
        git             \
        g++             \
        libc-dev        \
        linux-headers   \
        make            \
        openssl         \
        perl            \
        ruby            \
        ruby-dev        \
        wget            \
        yaml-dev        \
        zlib-dev        \
    && git clone https://github.com/unasuke/h2o.git \
    && cd h2o \
    && git checkout mruby-yaml \
    && cmake -DWITH_BUNDLED_SSL=on -DWITH_MRUBY=on . \
    && make install \
    && cd .. \
    && rm -rf h2o-* \
    && apk del builddeps \
    && apk add --no-cache --virtual=rundeps \
        libstdc++ \
        perl

RUN mkdir /etc/h2o

WORKDIR /etc/h2o

EXPOSE 80 443

COPY . /etc/h2o
CMD ["h2o", "--mode=master", "-c", "h2o.conf"]

Build h2o with mruby-yaml · unasuke/mruby_ac2016@4a3c552

yamlを読む

いろいろ準備が整ったので、yamlを読みこんでresponseを返していきます。

このようなyamlを用意しました。

data.yml
responses:
  -
    path: "/"
    message: "index"
  - 
    path: "/hoge"
    message: "hoge"
  - 
    path: "/fuga"
    message: "fuga"

そして、その内容に従ってresponseを返すように、mruby scriptを次のように書きかえます。

server.rb
class Server
  def call(env)
    response = fetch_response env['PATH_INFO']
    if response
      [200,
       {
         "content-type" => "text/plain; charset=utf-8",
       },
       [response]
      ]
    else
      [404,
       {
         "content-type" => "text/plain; charset=utf-8",
       },
       ["Not found"]
      ]
    end
  end

  def fetch_response(path)
    yaml = YAML.load(File.open('data.yml').read)
    message = nil
    yaml['responses'].each do |res|
      if res['path'] == path
        message = res['message']
      end
    end
    message
  end
end

Server.new

Return response from yaml · unasuke/mruby_ac2016@125a17b

docker buildしてrunすると、このようにyamlの内容に従ってresponseが返ってくるようになりました。

localhost:8080/
localhost:8080/hoge

余談

本当はhaconiwaのなかでh2oを動作させたかったのですが、どうにもうまくできず諦めました。

10
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3