Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Bandit

oss_survey/bandit.livemd

Bandit

Mix.install([
  {:bandit, "~> 1.0"},
  {:kino, "~> 0.13"},
  {:plug, "~> 1.16"}
])

サンプルコード

defmodule MyPlug do
  use Plug.Router

  plug(:match)
  plug(:dispatch)

  get "/" do
    send_resp(conn, 200, "Hello from Bandit on Livebook!")
  end

  match _ do
    send_resp(conn, 404, "Not found")
  end
end
{:ok, _} = Bandit.start_link(plug: MyPlug, port: 4000)

http://localhost:4000/

にアクセスする。

Banditの構造

Banditは、HTTPサーバーを提供するライブラリ。多機能なPhoenixと比べてシンプルなことが特長。

構成

ThousandIslandというTCPの処理を行うライブラリに依存している。
Bandit.startlinkで起動したプロセスに対するリクエストの処理方法は、各プロトコル(HTTP/1、HTTP2など)専用に Bandit.***.Handlerという形で実装されている。
内部的にGenServerを利用しているため、`handle
**`という関数群の処理を追うことで具体的なプロトコル処理が明らかになる。

Banditで通信プロトコルを処理してリクエストがElixirで扱えるようになったあとは、対応するインターフェースに処理を移譲する。上記の例ではPlugモジュールが処理を行う。

ElixirChip導入方針(コードリーディング方針)

  • 通信プロトコルのドメインを絞って、該当するHandlerを読み進める。
  • HTTPリクエストやレスポンス生成は、BanditではなくPlugを読み進める必要がある。

例として、HTTP/2のデシリアライズのコードを抜粋。

def deserialize(
      <>,
      max_frame_size
    )
    when length <= max_frame_size do
  type
  |> case do
    0x0 -> Bandit.HTTP2.Frame.Data.deserialize(flags, stream_id, payload)
    0x1 -> Bandit.HTTP2.Frame.Headers.deserialize(flags, stream_id, payload)
    0x2 -> Bandit.HTTP2.Frame.Priority.deserialize(flags, stream_id, payload)
    0x3 -> Bandit.HTTP2.Frame.RstStream.deserialize(flags, stream_id, payload)
    0x4 -> Bandit.HTTP2.Frame.Settings.deserialize(flags, stream_id, payload)
    0x5 -> Bandit.HTTP2.Frame.PushPromise.deserialize(flags, stream_id, payload)
    0x6 -> Bandit.HTTP2.Frame.Ping.deserialize(flags, stream_id, payload)
    0x7 -> Bandit.HTTP2.Frame.Goaway.deserialize(flags, stream_id, payload)
    0x8 -> Bandit.HTTP2.Frame.WindowUpdate.deserialize(flags, stream_id, payload)
    0x9 -> Bandit.HTTP2.Frame.Continuation.deserialize(flags, stream_id, payload)
    unknown -> Bandit.HTTP2.Frame.Unknown.deserialize(unknown, flags, stream_id, payload)
  end
  |> then(&{&1, rest})
end

参考