LT「mini Bandit」を作ってみる
Mix.install([
{:thousand_island, "~> 1.0"}
])
LTのゴール
- ちょっとBanditのコードが追えるようになる
- 小さいHTTPサーバーを動かす
Q. なぜBanditのコード読んでんの?
A. 本当はPhoenixをまるごと高速化したい!
が、いきなりまるごとできないので、機能を少しずつ切り出して高速化するため。
Banditってなに
https://github.com/mtrudel/bandit
TCP/TLS層はThousandIslandに任せて、HTTP1/HTTP2/WebSocket対応したシンプルなサーバー。
graph LR;
subgraph ThousandIsland
TCP-->TLS;
end
TLS-->HTTP1;
subgraph Bandit
HTTP1
HTTP2
WebSocket
end
TLS-->HTTP2;
TLS-->WebSocket;
今日の範囲
graph LR;
subgraph Today
HTTP1-->共通処理
end
HTTP2-->特有のいろいろ-->共通処理;
共通処理
-
レスポンスの作成
- ファイル読み込み
- HTTP1レスポンス
-
(HTTP2やりたかったけど動かんかった)
Bandit Code Reading
https://github.com/mtrudel/bandit
- bandit.ex
- ThousandIslandのHEx Docsを紹介
- https://hexdocs.pm/thousand_island/ThousandIsland.Handler.html
- Bandit.InitialHandler
- Bandit.HTTP1.Handler
mini Bandit
defmodule HTTPHelloWorld do
@moduledoc """
A sample Handler implementation of a simple HTTP Server. Intended to be the
simplest thing that can answer a browser request and nothing more. Not even
remotely strictly HTTP compliant.
"""
use ThousandIsland.Handler
@impl ThousandIsland.Handler
def handle_data(_data, socket, state) do
str = File.read!("./hello_world.html")
ThousandIsland.Socket.send(socket, "HTTP/1.0 200 OK\r\n\r\n#{str}")
{:close, state}
end
end
name = :my_thousand_server
pid = Process.whereis(name)
unless is_nil(pid), do: Supervisor.stop(pid)
{:ok, new_pid} = ThousandIsland.start_link(port: 1234, handler_module: HTTPHelloWorld)
Process.register(new_pid, name)
もうちょっとBanditっぽくした版
https://github.com/hisaway/codex_fragments/tree/main/mini_bandit