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

# はじめに
ElixirにてCowboyを直接動かすための記事となります。
[前回](http://qiita.com/hayabusa333/items/783ba7098fd598adb64b)の記事では、sendfileメソッドにて送信時に直接ファイルを送信する方法を実装しました。
今回の記事ではStream通信に関して記載していきます。

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

[Cowboy2.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/stream_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 |

# Stream通信

今回はStream通信についてです。
通信内容に関してはHTMLの通信を実施し、1つずつ画面の表示内容を増やしていきます。
画面だけ先に表示するためにStreamでの通信を行う場合などもあるかと思いますので役にたつのではないでしょうか。

## cowboy 1.0の場合

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # Add it.
      {"/stream", ElixirCowboyExample.StreamHandler, []},
      {"/sendfile", ElixirCowboyExample.SendFileHandler, []},
      {"/cookie", ElixirCowboyExample.CookieHandler, []},
      {"/upload", ElixirCowboyExample.UploadHandler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []},
      {"/priv/static/image/[...]", :cowboy_static, {:priv_dir, :elixir_cowboy_example, "static/image"}}
    ]

```

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

  def handle(req, state) do

    # stream通信を実施するための準備
    {:ok, req} = :cowboy_req.chunked_reply(200, req)

    # 2秒おきにHTML内容を送信実施する
    :ok = :cowboy_req.chunk("<html><head>Hello world!</head>", req)
    :timer.sleep(2000)
    :ok = :cowboy_req.chunk("<body><p>Stream!</p>", req)
    :timer.sleep(2000)
    :ok = :cowboy_req.chunk("<p>Output!</p></body></html>", req)

    {:ok, req, state}
  end

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

## cowboy 2.0の場合

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # Add it.
      {"/stream", ElixirCowboyExample.StreamHandler, []},
      {"/sendfile", ElixirCowboyExample.SendFileHandler, []},
      {"/cookie", ElixirCowboyExample.CookieHandler, []},
      {"/upload", ElixirCowboyExample.UploadHandler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []},
      {"/priv/static/image/[...]", :cowboy_static, {:priv_dir, :elixir_cowboy_example, "static/image"}}
    ]

```

``` elixir:lib/elixir_cowboy_example/stream_handler.ex
defmodule ElixirCowboyExample.StreamHandler do
  def init(req, opts) do

    # stream通信のための準備
    req = :cowboy_req.stream_reply(200, req)
    
    # 2秒おきにHTMLの内容を送信
    # cowboy2.0では通信を続ける間は、:nofin を設定し、完了時に :fin を送るように設定を実施する
    :cowboy_req.stream_body("<html><head>Hello world!</head>", :nofin, req)
    :timer.sleep(2000)
    :cowboy_req.stream_body("<body><p>Stream!</p>", :nofin, req)
    :timer.sleep(2000)
    :cowboy_req.stream_body("<p>Output!</p></body></html>", :fin, req)

    {:ok, req, opts}
  end

end
```

# 記載したコードの実行
コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り `iex -S mix` にて cowboy を実行していき、`http://localhost:4000/sendfile`にアクセスしてみましょう。
2秒おきにHTMLの内容が追加で表示されれば成功です。

<img width="1176" alt="スクリーンショット 2017-01-16 10.19.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/a3307b1a-355e-dcc0-e2f5-77c0d39e026f.png">


# 最後に

今回はstream通信を実施する方法を記載してきました。
上記でも記載しましたが、一括で送信するのではなくstreamで通信したいこともありますので役にたつのではないでしょうか。
それではまた次回

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