Phoenix v1.4.0 Phoenix.Endpoint behaviour View Source

Defines a Phoenix endpoint.

The endpoint is the boundary where all requests to your web application start. It is also the interface your application provides to the underlying web servers.

Overall, an endpoint has three responsibilities:

  • to provide a wrapper for starting and stopping the endpoint as part of a supervision tree

  • to define an initial plug pipeline for requests to pass through

  • to host web specific configuration for your application

Endpoints

An endpoint is simply a module defined with the help of Phoenix.Endpoint. If you have used the mix phx.new generator, an endpoint was automatically generated as part of your application:

defmodule YourApp.Endpoint do
  use Phoenix.Endpoint, otp_app: :your_app

  # plug ...
  # plug ...

  plug YourApp.Router
end

Endpoints must be explicitly started as part of your application supervision tree. Endpoints are added by default to the supervision tree in generated applications. Endpoints can be added to the supervision tree as follows:

children = [
  YourApp.Endpoint
]

Endpoint configuration

All endpoints are configured in your application environment. For example:

config :your_app, YourApp.Endpoint,
  secret_key_base: "kjoy3o1zeidquwy1398juxzldjlksahdk3"

Endpoint configuration is split into two categories. Compile-time configuration means the configuration is read during compilation and changing it at runtime has no effect. The compile-time configuration is mostly related to error handling and instrumentation.

Runtime configuration, instead, is accessed during or after your application is started and can be read through the config/2 function:

YourApp.Endpoint.config(:port)
YourApp.Endpoint.config(:some_config, :default_value)

Dynamic configuration

For dynamically configuring the endpoint, such as loading data from environment variables or configuration files, Phoenix invokes the init/2 callback on the endpoint, passing a :supervisor atom as first argument and the endpoint configuration as second.

All of Phoenix configuration, except the Compile-time configuration below can be set dynamically from the init/2 callback.

Compile-time configuration

  • :code_reloader - when true, enables code reloading functionality. For code the list of code reloader configuration options see Phoenix.CodeReloader.reload!/1

  • :debug_errors - when true, uses Plug.Debugger functionality for debugging failures in the application. Recommended to be set to true only in development as it allows listing of the application source code during debugging. Defaults to false

  • :render_errors - responsible for rendering templates whenever there is a failure in the application. For example, if the application crashes with a 500 error during a HTML request, render("500.html", assigns) will be called in the view given to :render_errors. Defaults to:

    [view: MyApp.ErrorView, accepts: ~w(html), layout: false]

    The default format is used when none is set in the connection

  • :instrumenters - a list of instrumenter modules whose callbacks will be fired on instrumentation events. Read more on instrumentation in the “Instrumentation” section below

Runtime configuration

  • :cache_static_manifest - a path to a json manifest file that contains static files and their digested version. This is typically set to “priv/static/cache_manifest.json” which is the file automatically generated by mix phx.digest

  • :check_origin - configure transports to check origin header or not. May be false, true, a list of hosts that are allowed, or a function provided as MFA tuple. Hosts also support wildcards.

    For example, using a list of hosts:

    check_origin: ["//phoenixframework.org", "//*.example.com"]

    or a custom MFA function:

    check_origin: {MyAppWeb.Auth, :my_check_origin?, []}

    The MFA is invoked with the request %URI{} as the first argument, followed by arguments in the MFA list

    Defaults to true.

  • :http - the configuration for the HTTP server. Currently uses Cowboy and accepts all options as defined by Plug.Cowboy. Defaults to false

  • :https - the configuration for the HTTPS server. Currently uses Cowboy and accepts all options as defined by Plug.Cowboy. Defaults to false

  • :force_ssl - ensures no data is ever sent via HTTP, always redirecting to HTTPS. It expects a list of options which are forwarded to Plug.SSL. By default it sets the “strict-transport-security” header in HTTPS requests, forcing browsers to always use HTTPS. If an unsafe request (HTTP) is sent, it redirects to the HTTPS version using the :host specified in the :url configuration. To dynamically redirect to the host of the current request, set :host in the :force_ssl configuration to nil

  • :secret_key_base - a secret key used as a base to generate secrets for encrypting and signing data. For example, cookies and tokens are signed by default, but they may also be encrypted if desired. Defaults to nil as it must be set per application

  • :server - when true, starts the web server when the endpoint supervision tree starts. Defaults to false. The mix phx.server task automatically sets this to true

  • :url - configuration for generating URLs throughout the app. Accepts the :host, :scheme, :path and :port options. All keys except :path can be changed at runtime. Defaults to:

    [host: "localhost", path: "/"]

    The :port option requires either an integer, string, or {:system, "ENV_VAR"}. When given a tuple like {:system, "PORT"}, the port will be referenced from System.get_env("PORT") at runtime as a workaround for releases where environment specific information is loaded only at compile-time.

    The :host option requires a string or {:system, "ENV_VAR"}. Similar to :port, when given a tuple like {:system, "HOST"}, the host will be referenced from System.get_env("HOST") at runtime.

    The :scheme option accepts "http" and "https" values. Default value is infered from top level :http or :https option. It is useful when hosting Phoenix behind a load balancer or reverse proxy and terminating SSL there.

    The :path option can be used to override root path. Useful when hosting Phoenix behind a reverse proxy with URL rewrite rules

  • :static_url - configuration for generating URLs for static files. It will fallback to url if no option is provided. Accepts the same options as url

  • :watchers - a set of watchers to run alongside your server. It expects a list of tuples containing the executable and its arguments. Watchers are guaranteed to run in the application directory, but only when the server is enabled. For example, the watcher below will run the “watch” mode of the webpack build tool when the server starts. You can configure it to whatever build tool or command you want:

    [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development",
        "--watch-stdin"]]

    The :cd option can be used on a watcher to override the folder from which the watcher will run. By default this will be the project’s root: File.cwd!()

    [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development",
        "--watch-stdin"], cd: "my_frontend"]
  • :live_reload - configuration for the live reload option. Configuration requires a :patterns option which should be a list of file patterns to watch. When these files change, it will trigger a reload. If you are using a tool like pow in development, you may need to set the :url option appropriately.

    live_reload: [
      url: "ws://localhost:4000",
      patterns: [
        ~r{priv/static/.*(js|css|png|jpeg|jpg|gif)$},
        ~r{web/views/.*(ex)$},
        ~r{web/templates/.*(eex)$}
      ]
    ]
  • :pubsub - configuration for this endpoint’s pubsub adapter. Configuration either requires a :name of the registered pubsub server or a :name and :adapter pair. The pubsub name and adapter are compile time configuration, while the remaining options are runtime. The given adapter and name pair will be started as part of the supervision tree. If no adapter is specified, the pubsub system will work by sending events and subscribing to the given name. Defaults to:

    [adapter: Phoenix.PubSub.PG2, name: MyApp.PubSub]

    It also supports custom adapter configuration:

    [name: :my_pubsub, adapter: Phoenix.PubSub.Redis,
     host: "192.168.100.1"]

Endpoint API

In the previous section, we have used the config/2 function that is automatically generated in your endpoint. Here’s a list of all the functions that are automatically defined in your endpoint:

Instrumentation

Phoenix supports instrumentation through an extensible API. Each endpoint defines an instrument/3 macro that both users and Phoenix internals can call to instrument generic events. This macro is responsible for measuring the time it takes for the event to be processed and for notifying a list of interested instrumenter modules of this measurement.

You can configure this list of instrumenter modules in the compile-time configuration of your endpoint. (see the :instrumenters option above). The way these modules express their interest in events is by exporting public functions where the name of each function is the name of an event. For example, if someone instruments the :render_view event, then each instrumenter module interested in that event will have to export render_view/3.

Callbacks cycle

The event callback sequence is:

  1. The event callback is called before the event happens (in this case, before the view is rendered) with the atom :start as the first argument; see the “Before clause” section below
  2. The event occurs (in this case, the view is rendered)
  3. The same event callback is called again, this time with the atom :stop as the first argument; see the “After clause” section below

The second and third argument that each event callback takes depends on the callback being an “after” or a “before” callback i.e. it depends on the value of the first argument, :start or :stop. For this reason, most of the time you will want to define (at least) two separate clauses for each event callback, one for the “before” and one for the “after” callbacks.

All event callbacks are run in the same process that calls the instrument/3 macro; hence, instrumenters should be careful to avoid performing blocking actions. If an event callback fails in any way (exits, throws, or raises), it won’t affect anything as the error is caught, but the failure will be logged. Note that “after” callbacks are not guaranteed to be called as, for example, a link may break before they’ve been called.

“Before” clause

When the first argument to an event callback is :start, the signature of that callback is:

event_callback(:start, compile_metadata, runtime_metadata)

where:

  • compile_metadata is a map of compile-time metadata about the environment where instrument/3 has been called. It contains the module where the instrumentation is happening (under the :module key), the file and line (:file and :line), and the function inside which the instrumentation is happening (under :function). This information can be used arbitrarily by the callback
  • runtime_metadata is a map of runtime data that the instrumentation passes to the callbacks. This can be used for any purposes: for example, when instrumenting the rendering of a view, the name of the view could be passed in these runtime data so that instrumenters know which view is being rendered (instrument(:view_render, %{view: "index.html"}, fn ...))

“After” clause

When the first argument to an event callback is :stop, the signature of that callback is:

event_callback(:stop, time_diff, result_of_before_callback)

where:

  • time_diff is an integer representing the time it took to execute the instrumented function in native units

  • result_of_before_callback is the return value of the “before” clause of the same event_callback. This is a means of passing data from the “before” clause to the “after” clause when instrumenting

The return value of each “before” event callback will be stored and passed to the corresponding “after” callback.

Using instrumentation

Each Phoenix endpoint defines its own instrument/3 macro. This macro is called like this:

require MyApp.Endpoint
MyApp.Endpoint.instrument(:render_view, %{view: "index.html"}, fn ->
  # actual view rendering
end)

All the instrumenter modules that export a render_view/3 function will be notified of the event so that they can perform their respective actions.

Phoenix default events

By default, Phoenix instruments the following events:

  • :phoenix_controller_call - the entire controller pipeline. The %Plug.Conn{} is passed as runtime metadata
  • :phoenix_controller_render - the rendering of a view from a controller. The map of runtime metadata passed to instrumentation callbacks has the :view key - for the name of the view, e.g. HexWeb.ErrorView, the :template key - for the name of the template, e.g., "index.html", the :format key - for the format of the template, and the :conn key - containing the %Plug.Conn{}
  • :phoenix_error_render - the rendering of an error view when an exception, throw, or exit is caught. The map of runtime metadata contains the :status key of the error’s HTTP status code, the :conn key containg the %Plug.Conn{}, as well as the :kind, :reason, and :stacktrace of the caught error
  • :phoenix_channel_join - the joining of a channel. The %Phoenix.Socket{} and join params are passed as runtime metadata via :socket and :params
  • :phoenix_channel_receive - the receipt of an incoming message over a channel. The %Phoenix.Socket{}, payload, event, and ref are passed as runtime metadata via :socket, :params, :event, and :ref
  • :phoenix_socket_connect - the connection of the user socket transport. The map of runtime metadata contains the :transport, :params, a map of connect_info, and the :user_socket module.

Dynamic instrumentation

If you want to instrument a piece of code, but the endpoint that should instrument it (the one that contains the instrument/3 macro you want to use) is not known at compile time, only at runtime, you can use the Phoenix.Endpoint.instrument/4 macro. Refer to its documentation for more information.

Link to this section Summary

Functions

Instruments the given function using the instrumentation provided by the given endpoint

Checks if Endpoint’s web server has been configured to start

Defines a websocket/longpoll mount-point for a socket

Callbacks

Broadcasts a msg as event in the given topic

Broadcasts a msg as event in the given topic

Broadcasts a msg from the given from as event in the given topic

Broadcasts a msg from the given from as event in the given topic

Access the endpoint configuration given by key

Reload the endpoint configuration on application upgrades

Initialize the endpoint configuration

Allows instrumenting operation defined by function

Generates the path information when routing to this endpoint

Starts the endpoint supervision tree

Generates a route to a static file in priv/static

Generates the static URL without any path information

Generates the endpoint base URL, but as a URI struct

Subscribes the caller to the given topic

Unsubscribes the caller from the given topic

Generates the endpoint base URL without any path information

Link to this section Types

Link to this section Functions

Link to this macro instrument(endpoint_or_conn_or_socket, event, runtime \\ Macro.escape(%{}), fun) View Source (macro)

Instruments the given function using the instrumentation provided by the given endpoint.

To specify the endpoint that will provide instrumentation, the first argument can be:

  • a module name - the endpoint itself
  • a Plug.Conn struct - this macro will look for the endpoint module in the :private field of the connection; if it’s not there, fun will be executed with no instrumentation
  • a Phoenix.Socket struct - this macro will look for the endpoint module in the :endpoint field of the socket; if it’s not there, fun will be executed with no instrumentation

Usually, users should prefer to instrument events using the instrument/3 macro defined in every Phoenix endpoint. This macro should only be used for cases when the endpoint is dynamic and not known at compile time.

Examples

endpoint = MyApp.Endpoint
Phoenix.Endpoint.instrument endpoint, :render_view, fn -> ... end
Link to this function server?(otp_app, endpoint) View Source

Checks if Endpoint’s web server has been configured to start.

  • otp_app - The OTP app running the endpoint, for example :my_app
  • endpoint - The endpoint module, for example MyApp.Endpoint

Examples

iex> Phoenix.Endpoint.server?(:my_app, MyApp.Endpoint)
true
Link to this macro socket(path, module, opts \\ []) View Source (macro)

Defines a websocket/longpoll mount-point for a socket.

Note: for backwards compatibility purposes, the :websocket and :longpoll options only have an effect if the socket given as argument has no transport declarations in it.

Options

  • :websocket - controls the websocket configuration. Defaults to true. May be false or a keyword list of options. See “Shared configuration” and “WebSocket configuration” for the whole list

  • :longpoll - controls the longpoll configuration. Defaults to false. May be true or a keyword list of options. See “Shared configuration” and “Longpoll configuration” for the whole list

  • :shutdown - the maximum shutdown time of each channel when the endpoint is shutting down. Applies only to channel-based sockets

Examples

socket "/ws", MyApp.UserSocket

socket "/ws/admin", MyApp.AdminUserSocket,
  longpoll: true,
  websocket: [compress: true]

Shared configuration

The configuration below can be given to both :websocket and :longpoll keys:

  • :serializer - a list of serializers for messages. See Phoenix.Socket for more information

  • :transport_log - if the transport layer itself should log and, if so, the level

  • :check_origin - if we should check the origin of requests when the origin header is present. It defaults to true and, in such cases, it will check against the host value in YourApp.Endpoint.config(:url)[:host]. It may be set to false (not recommended) or to a list of explicitly allowed origins.

    check_origin: ["https://example.com",
                   "//another.com:888", "//other.com"]

    Note: To connect from a native app be sure to either have the native app set an origin or allow any origin via check_origin: false

  • :code_reloader - enable or disable the code reloader. Defaults to your endpoint configuration

  • :connect_info - a list of keys that represent data to be copied from the transport to be made available in the user socket connect/3 callback

    The valid keys are:

    • :peer_data - the result of Plug.Conn.get_peer_data/1
    • :x_headers - all request headers that have an “x-“ prefix
    • :uri - a %URI{} with information from the conn

    Arbitrary keywords may also appear following the above valid keys, which is useful for passing custom connection information to the socket.

    For example:

    socket "/socket", AppWeb.UserSocket,
      websocket: [
        connect_info: [:peer_data, :x_headers, :uri]
      ]

    With arbitrary keywords:

    socket "/socket", AppWeb.UserSocket,
      websocket: [
        connect_info: [:uri, signing_salt: "NZIguRPO"]
      ]

Websocket configuration

The following configuration applies only to :websocket.

  • :timeout - the timeout for keeping websocket connections open after it last received data, defaults to 60_000ms

Longpoll configuration

The following configuration applies only to :longpoll:

  • :window_ms - how long the client can wait for new messages in its poll request

  • :pubsub_timeout_ms - how long a request can wait for the pubsub layer to respond

  • :crypto - options for verifying and signing the token, accepted by Phoenix.Token. By default tokens are valid for 2 weeks

Link to this section Callbacks

Link to this callback broadcast!(topic, event, msg) View Source
broadcast!(topic(), event(), msg()) :: :ok | no_return()

Broadcasts a msg as event in the given topic.

Raises in case of failures.

Link to this callback broadcast(topic, event, msg) View Source
broadcast(topic(), event(), msg()) :: :ok | {:error, term()}

Broadcasts a msg as event in the given topic.

Link to this callback broadcast_from!(from, topic, event, msg) View Source
broadcast_from!(from :: pid(), topic(), event(), msg()) :: :ok | no_return()

Broadcasts a msg from the given from as event in the given topic.

Raises in case of failures.

Link to this callback broadcast_from(from, topic, event, msg) View Source
broadcast_from(from :: pid(), topic(), event(), msg()) ::
  :ok | {:error, term()}

Broadcasts a msg from the given from as event in the given topic.

Link to this callback config(key, default) View Source
config(key :: atom(), default :: term()) :: term()

Access the endpoint configuration given by key.

Link to this callback config_change(changed, removed) View Source
config_change(changed :: term(), removed :: term()) :: term()

Reload the endpoint configuration on application upgrades.

Link to this callback init(atom, config) View Source
init(:supervisor, config :: Keyword.t()) :: {:ok, Keyword.t()}

Initialize the endpoint configuration.

Invoked when the endpoint supervisor starts, allows dynamically configuring the endpoint from system environment or other runtime sources.

Link to this macrocallback instrument(instrument_event, runtime_metadata, function) View Source
instrument(
  term(),
  instrument_event :: Macro.t(),
  runtime_metadata :: Macro.t(),
  function :: Macro.t()
) :: Macro.t()

Allows instrumenting operation defined by function.

runtime_metadata may be omitted and defaults to nil.

Read more about instrumentation in the “Instrumentation” section.

Generates the path information when routing to this endpoint.

Starts the endpoint supervision tree.

Starts endpoint’s configuration cache and possibly the servers for handling requests.

Link to this callback static_path(path) View Source
static_path(path :: String.t()) :: String.t()

Generates a route to a static file in priv/static.

Link to this callback static_url() View Source
static_url() :: String.t()

Generates the static URL without any path information.

Link to this callback struct_url() View Source
struct_url() :: URI.t()

Generates the endpoint base URL, but as a URI struct.

Link to this callback subscribe(topic, opts) View Source
subscribe(topic(), opts :: Keyword.t()) :: :ok | {:error, term()}

Subscribes the caller to the given topic.

See Phoenix.PubSub.subscribe/3 for options.

Link to this callback unsubscribe(topic) View Source
unsubscribe(topic()) :: :ok | {:error, term()}

Unsubscribes the caller from the given topic.

Generates the endpoint base URL without any path information.