https://beam-lang.connpass.com/event/240399/
Plug & WAF2022-02-27 tokyo.ex #16
View Slide
agenda● About Me● ゴール● WAFとは何か● Webアプリ(MVC)の構造● 何故Plugが必要なのか● Plugの構造● Plugのインターフェース● Plugのデータフロー● DEMO● まとめ
About Me● おーはら / Twitter: @ohrdev / Github: ohr486● 株式会社ドリコム SRE部 部長○ Work:■ エンジニアマネージャ● 技術戦略の策定/推進● エンジニア採用/採用戦略策定■ サーバー/インフラエンジニア● 開発現場でゲームのバックエンド (Rails/Phoenix/Go/HCL)のコード書いてます■ 新規事業/ディレクター● 負荷試験支援/DevOps推進支援/設計コンサル● Community○ tokyo.ex / Japan Elixir Association / Erlang&Elixir Fest● Hobby○ 仏像制作○ 自転車
ゴール● ターゲット○ Plugが何をしているか理解したい人○ 何故Plugがあるかを理解したい人○ PhoenixとPlugの関係について理解したい人● ゴール○ (Phoenixを含む)WAFの構造について理解する○ Plugの構造について理解する○ PhoenixとPlugの関係について理解する
WAFとは何か● WAF = Web Application Framework○ elixir -> phoenix○ ruby -> rails○ python -> django● Webアプリを作るためのフレームワーク○ webアプリとは?■ インターネット/ネットワークを介して利用するアプリケーション■ ここでは、webブラウザ上で動作するという前提で進めます○ ex) wiki, blog, 掲示板, ECサイト, etc
Webアプリ(MVC)の構造WebサーバーWebアプリデータベースNginxApacheCowboyetcプロトコルHTTPWebSocketPhoenixRailsDjangoetcMySQLPostgreSQLSpanneretcDB I/FEctoActiveRecordetcWAF I/FPlugRackWSGIetccowboyPlugPhoenixEndpointRouterPipelineControllerView TemplateEctoDBViewControllerModel
何故Plugが必要なのか● 歴史的背景○ WAFの乱立とWebサーバーの多様化により、 WAFとWebサーバーの接続部分の組み合わせ爆発が発生し、全ての接続を網羅するのが難しくなった○ この問題を解決する為、 WAFとWebサーバーの統一的な I/Fを定めた仕様が策定された○ WAF,Webサーバー共に、この I/Fに対応すればどの組み合わせの接続も担保できるWAF1WAF2WAF3フレームワーク WebサーバーApachenginxlighttpd……WAF1WAF2WAF3フレームワーク WebサーバーApachenginxlighttpd共通のI/FPhoenix cowboyPlugRails nginxRack
Plugの構造cowboyPlug(I/F)PhoenixEndpointRouterPipelineControllerView TemplateHTTPコネクションのリクエスト/レスポンスを抽象化した構造体%Plug.Conn %Plug.ConnPlug%Plug.ConnHTTPRequestHTTPResponsePlug Plug Plug PlugPhoenixではPlugとして実装されているPlug PlugConn Conn’ Conn’’PlugとはConnを受け取り、Connの内部情報を更新して返却するモジュール/関数pipeline
Plugのインターフェース● Plugは以下の2つに分類される○ Function Plugs○ Module Plugs○ これらのPlugはplugマクロを使って、コントローラー層/Routerに差し込まれる■ https://github.com/ohr486/tokyoex_16_sample/blob/main/plug_sample/lib/plug_sample/router.ex#L8-L12● Function Plugs○ Plug.Connとオプションを引数にとり、Plug.Connを返却する関数■ (Plug.Conn.t, Plug.opts) :: Plug.Conn.t○ https://github.com/ohr486/tokyoex_16_sample/blob/main/plug_sample/lib/plug_sample/router.ex#L31● Module Plugs○ 以下の2つの関数をexportするモジュール■ init/1 : 引数のオプションを使って自身を初期化する関数、 コンパイル時に実行される■ call/2 : Plug.Connとオプションを引数にとり、Plug.Connの内部情報を更新して返却する関数○ https://github.com/ohr486/tokyoex_16_sample/blob/main/plug_sample/lib/plug_sample/module_plug.ex
PlugのデータフローFuncPlugModulePlugConn Conn’ Conn’’HTTPRequestHTTPResponsefunc_plug(conn, opts) ModulePlug.call(conn’, opts)ModulePlug.init(opts)compile時に呼出defmodule MyAppMod.Router douse Plug.Router…plug :func_plugplug ModulePlug…endPlug.Routerによる定義plugを通過する際に呼出 plugを通過する際に呼出
DEMOサンプルコードhttps://github.com/ohr486/tokyoex_16_sample/tree/main/plug_sample
まとめ● WAFとPlugの構造について紹介しました● 何故Plugが必要なのかについて紹介しました● PhoenixのRoutingやHTTP層の実装のCodeReadingをする際、%Plug.Connのデータ構造を追っていくと理解しやすいです● 独自実装のカスタムPlugは簡単に作成できます、PlugはHTTPリクエスト/レスポンスのデータ構造をダイレクトに操作できるので非常に強力で有用です