3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PhoenixフレームワークにおけるHTTP通信とWebソケット通信①~Plug.connについて~

Posted at

はじめに

ElixirでのWebアプリケーション開発において出会う様々な用語や概念を深堀します。今回は、Phoenixフレームワークを使用した際のHTTP通信とWebソケット通信の違いに焦点を当てて解説していきます。

Phoenixフレームワークにおけるクライアントとサーバー間でのデータのやり取り

Phoenixフレームワークでは、HTTP通信とWebソケット通信の両方がサポートされています。これにより、静的なウェブページの提供からリアルタイム通信を必要とするアプリケーションまで、幅広いニーズに対応できます。

HTTP通信とWebソケット通信の特徴

HTTP通信


  • 非持続的な接続: HTTPはリクエスト/レスポンスモデルに基づいており、クライアントがリクエストを送信した後にサーバーからレスポンスを受け取ると、その接続は通常終了
  • ステートレス: 各HTTPリクエストは独立しており、以前のリクエストからの情報は保存されません(セッションやクッキーを使用して間接的に状態を管理する方法はある)
  • リクエスト主導型: データの交換はクライアントからのリクエストによってのみ開始

Webソケット通信


  • 持続的な接続: Webソケットは接続を確立した後、その接続を開いたままにしておくことで、サーバーとクライアント間でリアルタイムのデータ交換が可能
  • 双方向通信: サーバーとクライアントは、接続が開いている間はいつでもお互いにデータを送信できます。これにより、リアルタイムアプリケーションの実装が容易に
  • フルデュプレックス通信: サーバーとクライアントは同時にデータを送受信できるため、より効率的な通信が可能

HTTP通信の実装方法

Phoenixフレームワークでは、Plug.Connを使用してHTTPリクエストの情報を取得し、レスポンスを構築します。

defmodule MyAppWeb.MyController do
  use MyAppWeb, :controller
  import Plug.Conn, only: [get_req_header: 2]

  def my_action(conn, _params) do
    headers = conn.req_headers
    user_agent = get_req_header(conn, "user-agent")
    text(conn, "User-Agent: #{user_agent}")
  end
end


参考hexdocs: Plug.Conn

Plugライブラリとは


ElixirでHTTPミドルウェアとアプリケーションを構築するための仕組みを提供するライブラリです。Plugを使用することで、開発者はリクエスト処理のパイプラインを簡単に定義し、リクエストの変換や特定の条件下でのレスポンスの返し方を制御できます。

Plug.Connとは


Plug.Connとは、HTTP接続(リクエストとレスポンス)を処理するための構造体とユーティリティ関数を提供するものです。
Plug.Connを使用することで開発者はリクエストの受け取りからレスポンスの生成に至るまでの処理を細かく制御できます。この構造体を使うことで、認証、データのバリデーション、レスポンスのカスタマイズなど、リクエストのライフサイクルにわたってさまざまな処理を効率的かつ柔軟に、実行できるようになります。

コード内で出てくるconnとは


先ほどの例で出てきたconnPlug.Conn構造体のインスタンスです。このconnオブジェクトを通してHTTPリクエストの処理とHTTPレスポンスの生成が行われます。

connの具体的な渡され方


Phoenixフレームワークを使用するWebアプリケーションでは、HTTPリクエストがサーバーに届くと、Plugパイプラインを通じて処理が行われ、最終的に特定のコントローラーのアクション(関数)にconnが渡されます。

Plugパイプラインはrouter.exの以下のような設定

 pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, html: {HelloServerWeb.Layouts, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug :fetch_current_user
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", PjCanolaServerWeb do
    pipe_through [:browser, :require_verify_header]

    live "/", PageLive
  end

ファイル内で定義されているpipeline :browser doブロックやpipeline :api doブロック内にあるplug宣言は、Plugパイプラインの一部です。
これらのplugは、Phoenixフレームワークがリクエストを処理する際に、Plug.Conn構造体を通して順番に実行される一連のミドルウェア(または操作)を定義しています。

上記のplug :fetch_current_userの定義は以下。

  @spec fetch_current_user(Plug.Conn.t(), keyword()) :: Plug.Conn.t()
  def fetch_current_user(conn, _opts) do
    {user_token, conn} = ensure_user_token(conn)
    user = user_token && Accounts.get_user_by_session_token(user_token)
    conn = assign(conn, :current_user, user)
  end

リクエストに含まれるユーザートークンを使用して現在のユーザーを識別し、その情報をconnに割り当てることで、以降の処理でユーザー情報に基づいたロジックを実行できるようにしています。

基本の整理

基本が曖昧な初学者向けに(私w)上記以外のことも整理しました。

パイプラインとは


pipeline :browser do ... endのように定義されるパイプラインは、その中に含まれる一連のplugによって構成されます。Phoenixにおいてパイプラインはplugパイプライのみなのでパイプライン=Plugパイプラインです。(PhoenixフレームワークおよびPlugライブラリにおけるパイプラインは、一連のplugを通じてHTTPリクエストを処理するためのメカニズムという意味です。)
つまり、Plug.Conn構造体を通して一連のplug処理を行うことを意味します。ここでのplugは、リクエストを受け取り、何らかの操作を施し、次のplugへ渡す関数またはモジュールです。
それをまとめたのがパイプラインとなります。

パイプラインの役割


  • コンテントタイプの受け入れ
  • セッションの取得と管理
  • フラッシュメッセージの取得
  • CSRF保護の適用
  • セキュリティヘッダーの追加
  • 現在のユーザーの取得

トークンとは


トークンは、認証やセッション管理においてユーザーを一意に識別するために使用される文字列です。ウェブアプリケーションにおいて、トークンはユーザーがログインした際に生成され、クライアント(例えば、ブラウザのクッキー)に保存されることが多いです。その後のリクエストでは、このトークンをサーバーに送信してユーザーを認証します。

まとめ

パイプラインを定義することで、複数のルートやコントローラー間で共通の処理を再利用できるようになります。例えば、ウェブアプリケーションの全てのページに対する共通のセキュリティポリシーを適用する場合、それをパイプライン内で定義し、必要なルートにpipe_throughを使用して適用します。

パイプラインは、PhoenixやPlugにおいて非常に強力な概念であり、HTTPリクエストの処理を柔軟かつ効率的に構成するためのキーとなります。

最後に

PhoenixフレームワークはHTTP通信とWebソケット通信の二つの通信方法が混在しており、Plug.connはHTTP通信なんだという理解ができるとセッション管理のあたりが徐々にわかってきました。

誤りなどありましたらご指摘お願いします!
また、thewaggleではElixirでの開発にジョインしてくださる仲間を募集しています!
ご興味ある方、お気軽にご連絡ください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?