どうも、靖宗です。
今回はEndpointということでPlugのところでもちょっとやったところです。
全てのリクエストはまずEndpointに渡されて、その後にルーティング処理に入ります。
そもそもPhoenixは一番最初にEndpointをSupervisorの管理下に起動するようです。
lib/hello_phoenix/application.ex
を確認します。
defmodule HelloPhoenix.Application do # See https://hexdocs.pm/elixir/Application.html # for more information on OTP Applications @moduledoc false use Application def start(_type, _args) do # List all child processes to be supervised children = [ # Start the Ecto repository HelloPhoenix.Repo, # Start the endpoint when the application starts HelloPhoenixWeb.Endpoint # Starts a worker by calling: HelloPhoenix.Worker.start_link(arg) # {HelloPhoenix.Worker, arg}, ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: HelloPhoenix.Supervisor] Supervisor.start_link(children, opts) end # Tell Phoenix to update the endpoint configuration # whenever the application is updated. def config_change(changed, _new, removed) do HelloPhoenixWeb.Endpoint.config_change(changed, removed) :ok end end
Endpointがchildrenに入っており、Supervisor.start_link(children, opts)
が実行されています。
Endpoint Contents
Phoenixのプロジェクトを開始した際に自動で生成されるlib/hello_phoenix_web/endpoint.ex
の中を見ていきます。
defmodule HelloPhoenixWeb.Endpoint do ... end
まず最初に
use Phoenix.Endpoint, otp_app: :hello
とあります。PhoenixのEndpointとして利用するためにuse
で様々な機能を呼び出しています。
otp_app: :hello
は設定用に用いられると記載がありますので、おそらくconfig/config.exs
に記載がある
# Configures the endpoint config :hello_phoenix, HelloPhoenixWeb.Endpoint, ...
の箇所の設定などが適応されるのでしょう。
次はSocketの設定。
socket "/socket", HelloPhoenixWeb.UserSocket, websocket: true, longpoll: false
RoutingのChannelの箇所でも見ましたが、websocketの設定だと思います。
詳しくはChannelsの章に回します。
次はPlug.Static
が適応されています。名前からしても静的ファイルの配信などでしょう。
plug Plug.Static, at: "/", from: :hello_phoenix, gzip: false, only: ~w(css fonts images js favicon.ico robots.txt)
圧縮を適応したり配信ファイルを設定したりフィルタリング(該当する静的ファイルのリクエストに対してのみ圧縮ファイルを利用するとか?)の設定とかできそうです。
次はコードリロードが適応されてるかどうかの処理。
if code_reloading? do socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket plug Phoenix.LiveReloader plug Phoenix.CodeReloader end
コードリロードはwebsocketで実装されてるんですかね。
主にホットリロードの機能は開発時のみに適応されます。ホットリロードのON/OFFはconfig/config.exs
のEndpointの箇所で設定するようです。
config :hello_phoenix, HelloPhoenixWeb.Endpoint, code_reloader: true
お次はPlug.RequestId
とPlug.Logger
。以前にちょっとだけ言及した気はしますがPlug.RequestId
が各リクエストに対してユニークなIDを降るPlugで、Plug.Logger
はロギングでしょう。
より詳しく知るにはPlugのModulesを閲覧するのが良さそうです。今はスルーします。
次は公式ドキュメントでの言及はありませんでしたが、Plug.Parsers
とPlug.MethodOverride
、Plug.Head
。これもルーティングのところで言及していますが、
Plug.Parsers
がリクエストの本体をパースするPlug、
Plug.MethodOverride
がmethodのパラメータからPOSTのリクエストをPUT、PATCH、DELETEに書き換えるPlug、
Plug.Head
がHEADリクエストをGETリクエストに変換するPlugです。
plug Plug.Parsers, parsers: [:urlencoded, :multipart, :json], pass: ["*/*"], json_decoder: Phoenix.json_library() plug Plug.MethodOverride plug Plug.Head
お次にPlug.Session
。名前の通りCookiesなどセッション情報の処理をするPlugでしょう。
plug Plug.Session, store: :cookie, key: "_hello_phoenix_key", signing_salt: "hogefuga"
最後にルーティング機能のPlugを呼び出しています。同じディレクトリにあるrouter.ex
が該当します。
plug HelloPhoenixWeb.Router
もっと色々知りたい人はEndpoint API docsを読むといいよ!と書かれています。今回はスルーしますが、必要に応じて確認したいところです。
Using SSL
SSLを使うときには設定を書き換えるのと2つの環境変数が必要なようです。
設定はconfig/prod.exs
に書き、otp_app: :hello_phoenix
を指定しているときは秘密鍵と証明書はpriv/
ディレクトリに入れとくようです。
use Mix.Config config :hello_phoenix, HelloPhoenixWeb.Endpoint, http: [port: {:system, "PORT"}], url: [host: "example.com"], cache_static_manifest: "priv/static/cache_manifest.json", https: [ port: 443, otp_app: :hello_phoenix, keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), certfile: System.get_env("SOME_APP_SSL_CERT_PATH"), # OPTIONAL Key for intermediate certificates: cacertfile: System.get_env("INTERMEDIATE_CERTFILE_PATH") ]
otp_app:
の値なしでの設定方法も書いてますが、ちょっとよく分からないのでスルーします。(PlugでPath.expand("../../../some/path/to/ssl/key.pem", __DIR__)
が必要って書いてあるけどどのPlug?)
TLSのバージョンなど厳密に指定したい場合はversions: [:'tlsv1.2']
などのキーを追加すればいいようですが、セキュリティ上望ましくないと思いますし気にしなくて良い気がします。
SSL in Development
開発時にSSLを使いたい時はmix phx.gen.cert
でオレオレ証明書(self-signed certificate)を発行できるようです。
開発時のみでの使用が推奨されますので、config/dev.exs
に記載します。
config :hello_phoenix, HelloPhoenixWeb.Endpoint, ... https: [ port: 4001, cipher_suite: :strong, keyfile: "priv/cert/selfsigned_key.pem", certfile: "priv/cert/selfsigned.pem" ]
Force SSL
SSLのページにリダイレクトしたいときとかの設定?
Endpointのコンフィグにforce_ssl:
を追記します。
:url
の設定に書いてねと言われてますのでconfig/prod.exs
とかでしょうか。若しくは開発時に試すためにconfig/dev.exs
。
config :hello_phoenix, HelloPhoenixWeb.Endpoint, force_ssl: [rewrite_on: [:x_forwarded_proto]]
ダイナミックにリダイレクト(たぶんhttp://hoge.com/api/fuga
→https://hoge.com/api/fuga
とか?)したい場合はhost: nil
を設定するようです。
config :my_app, MyApp.Endpoint, force_ssl: [rewrite_on: [:x_forwarded_proto], host: nil]
HSTS
HTTP Strict Transport Securityを適応したい場合はforce_ssl: :hsts
と書けば適応されるそうです。
ただし、ローカル環境での開発だとなんかしらんけど動かん、とかあるみたい(80への通信を強制的に443にリダイレクトするあたりが悪さする?)なんで、ブラウザごとで色々対策してねとあります。この辺を鑑みると開発用サーバーにデプロイするなど、HSTSを使う際にはあまりローカルで開発しない方がいいかもしれません。
SSLあたりはまだまだ勉強不足なので実際使ってみてまた何かあれば補足情報など記載したいと思います。