ElixirからCowboy 1.0と2.0を使ってみる Part 5

# はじめに
ElixirにてCowboyを直接動かすための記事となります。
[前回](http://qiita.com/hayabusa333/items/b5aa62af9e9bc45a9d83)の記事では、リクエストの情報からHTMLの内容の作成を行いました。
今回はcssやJavaScriptなどのスタティックファイルの読み込みを実施し、HTMLから操作できるようにしていきます。

[Cowboy1.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/static_file_cowboy)

[Cowboy2.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/static_file_cowboy_two_pre4)

# バージョン
使用した言語やライブラリのバージョンは下記となります。

## cowboy 1.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 1.0.4 |

## cowboy 2.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 2.0.0-pre4 |

# リクエスト情報からHTMLを作成

今回はcssやJavaScriptの情報をブラウザに渡す必要があります。
cssやJavaScriptの情報を渡す方法ですが、htmlと同じようにHandlerにて受け渡しを実施するだけで、特に難しいことはありません。
あとはhtmlに記述されているcssやJavaScriptが指定したURLにアクセスしてくれるため取得することができます。

## cowboy 1.0の場合

``` elixir:lib/elixir_cowboy_example/css_handler.ex
defmodule ElixirCowboyExample.CssHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do
    {method, req} = :cowboy_req.method(req)
    #routesで受け渡された :css の内容をparamに設定
    {param, req} = :cowboy_req.binding(:css, req)
    {:ok, req} = html_example(method, param, req)
    {:ok, req, state}
  end

  def html_example("GET", :undefined, req) do
    headers = [{"content-type", "text/css"}]
    body = ""
    {:ok, resp} = :cowboy_req.reply(404, headers, body, req)
  end

  #cssを受け渡しするためのHandler
  def html_example("GET", param, req) do
    headers = [{"content-type", "text/css"}]
    # paramに指定されたcssファイル名を取得し、replayにて返信する
    {:ok, file} = File.read "priv/static/css/#{param}"
    body = file
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def terminate(_reason, _req, _state) do
    :ok
  end
end
```

``` elixir:lib/elixir_cowboy_example/javascript_handler.ex
defmodule ElixirCowboyExample.JavascriptHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do
    {method, req} = :cowboy_req.method(req)
    #routesで受け渡された :javascript の内容をparamに設定
    {param, req} = :cowboy_req.binding(:javascript, req)
    {:ok, req} = html_example(method, param, req)
    {:ok, req, state}
  end

  def html_example("GET", :undefined, req) do
    headers = [{"content-type", "text/javascript"}]
    body = ""
    {:ok, resp} = :cowboy_req.reply(404, headers, body, req)
  end

  def html_example("GET", param, req) do
    headers = [{"content-type", "text/javascript"}]
    # paramに指定されたJavaScriptファイル名を取得し、replayにて返信する
    {:ok, file} = File.read "priv/static/js/#{param}"
    body = file
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end

  def terminate(_reason, _req, _state) do
    :ok
  end
end
```

``` elixir:lib/elixir_cowboy_example.ex
  def run do
    # routes に JavaScriptとcssを受け渡しするためのHandlerの設定
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []}
    ]

    dispatch = :cowboy_router.compile([{:_, routes}])

    opts = [port: 4000]
    env = [dispatch: dispatch]

    {:ok, _pid} = :cowboy.start_http(:http, 100, opts, [env: env])
  end
```

``` html:priv/static/html/index.html
<html>
  <head>
    <meta charset=\"utf-8\">
      <title>Cowboy Hello!</title>
    <script type="text/javascript" src="priv/static/js/main.js"></script>
    <link rel="stylesheet" type="text/css" href="priv/static/css/main.css">
  </head>
  <body>
    <h1>Cowboy Hello!!</h1>
    <h2>file load test<h2>
    <input class="button" type='submit' value='test' onclick="func()">
  </body>
</html>
```

``` css:priv/static/css/main.css
h1{
  color:red;
}
.button{
  width: 200px;
}
```

``` javascript:priv/static/js/main.js
function func(){
  window.alert("HELLO WORLD");
}
```

## cowboy 2.0の場合

``` elixir:lib/elixir_cowboy_example/css_handler.ex
defmodule ElixirCowboyExample.CssHandler do
  def init(req, opts) do
    method = :cowboy_req.method(req)
    #routesで受け渡された :css の内容をparamに設定
    param = :cowboy_req.binding(:css, req)
    {:ok, resp} = html_example(method, param, req)
    {:ok, resp, opts}
  end

  def html_example("GET", :undefined, req) do
    headers = %{"content-type" => "text/css"}
    body = ""
    {:ok, resp} = :cowboy_req.reply(404, headers, body, req)
  end

  def html_example("GET", param, req) do
    headers = %{"content-type" => "text/css"}
    # paramに指定されたcssファイル名を取得し、replayにて返信する
    {:ok, file} = File.read "priv/static/css/#{param}"
    body = file
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end
end
```

``` elixir:lib/elixir_cowboy_example/javascript_handler.ex
defmodule ElixirCowboyExample.JavascriptHandler do
  def init(req, opts) do
    method = :cowboy_req.method(req)
    #routesで受け渡された :javascript の内容をparamに設定
    param = :cowboy_req.binding(:javascript, req)
    {:ok, resp} = html_example(method, param, req)
    {:ok, resp, opts}
  end

  def html_example("GET", :undefined, req) do
    headers = %{"content-type" => "text/javascript"}
    body = ""
    {:ok, resp} = :cowboy_req.reply(404, headers, body, req)
  end

  def html_example("GET", param, req) do
    headers = %{"content-type" => "text/javascript"}
    # paramに指定されたJavaScriptファイル名を取得し、replayにて返信する
    {:ok, file} = File.read "priv/static/js/#{param}"
    body = file
    {:ok, resp} = :cowboy_req.reply(200, headers, body, req)
  end
end
```

``` elixir:lib/elixir_cowboy_example.ex
  def run do
    # routes に JavaScriptとcssを受け渡しするためのHandlerの設定
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []}
    ]

    dispatch = :cowboy_router.compile([{:_, routes}])

    opts = [{:port, 4000}]
    env = %{dispatch: dispatch}

    {:ok, _pid} = :cowboy.start_clear(:http, 100, opts, %{env: env})
  end
```

css、JavaScript、htmlなどのファイルは特に違いはありませんので、cowboy1.0の方を参考にしてください。

# 記載したコードの実行
コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り `iex -S mix` にて cowboy を実行していき、`http://localhost:4000/xxx`にアクセスしてみましょう。
下記のようにブラウザの画面に表示されるはずです。
またtestボタンを押下することによって、JavaScriptが動き、ダイアログが表示されます。

<img width="1392" alt="スクリーンショット 2017-01-10 10.16.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/bb1df6c5-9beb-5635-5a2a-af15f6f79bd2.png">

<img width="1280" alt="スクリーンショット 2017-01-10 10.17.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/30044fe7-ca79-0100-7d31-3953ceacf0f9.png">

# 最後に
今回はcssやJavaScriptなどのスタティックファイルをHTMLファイルで読み込み使用する方法を実装してみました。
cssやJavaScriptのファイル自体も指定のディレクトリに配置されていれば、Handlerを1つ記載するだけで読み込んで返せば使用することが上のコードからわかりました。
これでHTMLにて実施したい内容はほぼほぼ実施できるのではないでしょうか？
それではまた次回

# 参考サイト
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/1.0/guide/)
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/2.0/guide/)