This week I decided to push some things in the project. Instead of looking into the internals of Elixir and Erlang VM, let’s actually do something. My project for DSP competition is a web application, and most popular framework for web development in Elixir is called Phoenix. Phoenix use as it’s foundation Erlang’s HTTP server – Cowboy. I’m not gonna look into it right now, I don’t think it will be necessary at this point.
More important for now will be knowledge what is Plug. It is a specification for constructing modules, that can be composed together and configure how web applications behave. Modules and functions that are built to this specification are called Plugs. Plugs can be chained together to create pipelines and can handle nearly everything, i.e. authentication or parameter pre-processing. To learn more look into this guide.
Thanks to Plugs, Phoenix doesn’t have a need for a monolithic middleware. And you can customise every step of handling a request. Let’s look at the elements that handle a request up to rendering, step by step.
The Endpoint is responsible for handling request until the moment that routes take over. Which includes starting server, applying the configuration and also applying a set of plugs that are common for all requests.
The Router is responsible for a few things. First of all, it parses incoming requests and sends them to appropriate Controller and Action. You can also create Pipelines here, which are sequences of Plugs, that can be easily applied to routes. So on top of common plugs, you can add your own. For example, to differently handle requests that will be rendered in a browser, vs. API requests.
Controllers do what they usually do in MVC model. They provide actions, which may prepare data for views, render stuff (through Views) on screen or do redirects.
Views are presentation layer. They’re rendered based on Templates. Templates in Elixir are precompiled, which makes them very fast.
Armed with those basics, let’s look at some code that’s generated when you start Phoenix project.
First what I did is mix new Phoenix project instead of previous one.
$ mix phoenix.new hello_phoenix
This caused some havoc in my repository but I managed to clean it up. After this and few other steps, like setting up a database, I could start it up.
$ mix phoenix.server
After that I could navigate to http://localhost:4000/ to see my first Phoenix application:
Let’s take a look, how default Router looks like:
defmodule Flightlog.Router do use Flightlog.Web, :router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers end pipeline :api do plug :accepts, ["json"] end scope "/", Flightlog do pipe_through :browser # Use the default browser stack get "/", PageController, :index end # Other scopes may use custom stacks. # scope "/api", Flightlog do # pipe_through :api # end end
You can notice declared separate pipelines for browser and API. The one for browsers has accept-headers for HTML, handles session and adds anti-forgery tokens. One for API is much simpler. Then inside of scope (which is out of the scope of this post :P) you can see this pipeline applied and route for “/” declared that will trigger PageController’s action named :index.
defmodule Flightlog.PageController do use Flightlog.Web, :controller def index(conn, _params) do render conn, "index.html" end end
This renders a view based on template located in file index.html.eex.
Next week I’ll start working on the code and adjust the routes for my own needs.
If you interested into looking Phoenix yourself, their documentation is very good, especially the guides. I also watched this video from 2015 NDC Oslo by the creator of Phoenix, Chris McCord. It gave me good overview how things work in Phoenix.
Thanks for reading this another part of my adventures with Elixir and Phoenix. Come next week for more. And if you’re interested in machine learning, look into my weekly link drop.