Phoenix Framework from HTTP Request to Response
This post describes the steps that a HTTP request/response takes in a Phoenix Framework application. The example application described here was generated using the command mix phoenix.new hello_world
.
The steps in the HTTP request/response cycle are outlined as follows:
- HTTP Request
- Cowboy
- Plug
- Phoenix Endpoint
- Phoenix Router
- Phoenix Controller
- Phoenix View
- Phoenix Template
- Phoenix Endpoint
- Plug
- HTTP Response
HTTP Request
A browser user sends an HTTP GET request to http://localhost:4000/
.
The request is received by the Cowboy server.
Cowboy
Cowboy is an Erlang based HTTP server which is currently the only server with a Plug adapter implemented.
Cowboy will parse the HTTP request and the first Plug Connection will be created in Plug’s Cowboy adapter.
Plug
Plug is a web server interface for Elixir that provides a way to compose modules in a sequence during a request/response cycle.
Each plug module receives the HTTP request which is called a Plug Connection and often referred to as the variable conn
. The plug may transform and update the connection and then return an HTTP response immediately or pass the connection to the next plug in the sequence.
The Plug library has built in plugs that provide CSRF protection, sessions, logging, serving static files, and more.
Phoenix applications themselves are built by composing a series of plugs which are defined in a Phoenix Endpoint.
Phoenix Endpoint
The Phoenix Endpoint is found in the project file lib/hello_world/endpoint.ex
. The endpoint defines the plugs that will make up your application. It is the entry and exit point to the Phoenix application.
Each plug will be called in order as defined in the HelloWorld.Endpoint
. A plug such as the Plug.Static
plug may send a response before the connection is seen by other plugs. Note that the last plug defined is the router.
Phoenix Router
A Router defines an application’s pipelines and paths. If the given URL path matches based on the HTTP verb and path, the indicated controller action will be run.
Pipelines are defined using the pipeline
macro which describes a sequence of plugs to run on the connection. The scope
macros define which pipelines to run using the pipe_through
macro.
In this example, our GET request to http://localhost:4000/
will match get "/"
definition so the PageController.index
function will be called after the :browser
pipeline plugs are called with the connection. The :browser
pipeline is called because the get "/"
is defined inside a scope that specifies a pipeline using pipe_through
.
The Phoenix Router is analogous to the routes.rb
file in Ruby on Rails. The mix phoenix.routes
command will list the routes and path helpers defined by the router.
Phoenix Controller
The controller is where application logic is done. Often this will include running SQL queries using the Ecto
database library which is not covered in this article.
The params variable will contain a string keyed map of request parameters. Next, Phoenix.Controller.render/2
is called with the conn
and template name index.html
. Often, Phoenix.Controller.render/3
will be called with additional data to render like this: render conn, "index.html", [data: "data"]
.
The Phoenix.Controller.render/2
method will lookup the template file which by convention should be located in web/templates/page/index.html.eex
and will then call the Phoenix.View.render_to_iodata/3
function.
Phoenix View
Aside from rendering the template, the view also can provide helper functions and path helpers which will automatically be available to the template.
Phoenix Template
By default, an html formatted EEx template was generated. EEx means Embedded Elixir which allows Elixir code to be included in template files.
The index.html.eex
file that was generated only contains html by default. So, an alternative template example is shown here.
HTTP Response
After the view renders the template, the controller will then call the Plug send_resp
method with the rendered template data to return the HTTP response.
The user receives the rendered template in the browser.