How to Create Minimal Elixir Web App With Plug and Cowboy and Deploy to Heroku
This post will go through how to create a minimal web application in Elixir just using Cowboy, an HTTP server for Erlang/OTP, and Plug, a composable web middleware for Elixir, and deploy it to Heroku.
Since you are knowledgeable enough to know about and look for a barebone approach, I assume that you have a basic familiarity with both Elixir and web development.
I’m using Elixir 1.4.1 at the time of writing. The application directory structure and mix.exs
file configuration got changed in Elixir 1.4, so I recommend you to get Elixir 1.4 or higher to minimize discrepancy.
Complete source code of the finished sample application can be found here. Link to the running Heroku app is here.
Create an Elixir Application
In this post, we will create a simple application that converts datetime between iso8601 and unix formats.
Run mix new timeconverter --sup
from your shell to create a new Elixir app with built-in supervision tree.
Add HTTP Server
We will set up Cowboy and Plug. Open mix.exs
and add dependencies.
Then run mix deps.get
to fetch necessary dependencies.
After that, we will create Timeconverter.Router
module that will serve as the HTTP interface of the application. Create router.ex
in lib/timeconverter
directory. Copy the following code into the newly created file.
Plug.Router
provides a set of macros to generate routes that respond to HTTP reqeusts. When you use that module, match
and dispatch
plugs are required by default.
get "/"
will respond to GET requests made to the root page. All other requests will be routed to match _
.
Check the documentation for Plug.Router
from here.
start_link/3
function is a part of GenServer
, not Plug.Router
. It defines what Timeconverter.Router
module will do when it’s run under a supervision tree. Here we set it to run Cowboy
under HTTP.
Next we will include Timeconverter.Router
under the application’s supervision tree so that it will be run when the application runs. Open lib/timeconverter/application.ex
and add Timeconverter.Router
as a worker.
Now Cowboy
HTTP server will also run when our application runs.
Run mix run --no-halt
from the shell. If you are prompted to install rebar
dependency, do so. When the application runs, open up localhost:4000
. You will see the application running, greeting you with a simple text “wow!”.
Add Domain Logic for Converting Time Format
Since this post is about building a minimal web app and deploying it, we will not go into the domain logic itself. It’s a pretty boring example, anyway.
Replace the contents of lib/timeconverter.ex
with the following code. Remember that this sample code is also provided on github.
Nothing interesting here - just some Regex and DateTime functions. Let’s look at how we connect the HTTP routes with domain logic. Open lib/timeconverter/router.ex
and change the route functions.
Plug.Conn
could be understood as the representation of HTTP requests and responses. All useful information about a single HTTP connection is stored in one Plug.Conn
struct and can be accessed from there.
Query parameters can be accessed from conn.params
only after running Plug.Conn.fetch_query_params/1
. After getting the parameters, we pass conn.params
to our domain logic function Timeconverter.convert_datetime/1
. As you can see, connecting HTTP endpoint layer and domain logic is simple and straightforward.
Quit the application and run it again. Now the app will respond to different query parameters.
Deploying to Heroku
You need Heroku account and Heroku Command Line Interface for this part. If you haven’t set it up already, visit Heroku dev center and follow the instructions.
We need buildpacks to deploy to Heroku. Although Elixir is not officially supported, there’s an open source buildpack for Elixir created by HashNuke. We will use that buildpack to deploy to Heroku. Check the documentation for HashNuke’s buildpack from here.
But we need to make a few preparations before deploying. First create elixir_buildpack.config
file in the application’s root directory and type the following configurations.
As of February 2017 the buildpack uses Elixir 1.3 when no Elixir version is specified. Since we’re using Elixir 1.4, the build causes error if we don’t specify the Elixir version we’d like to use.
Now open lib/timeconverter/router.ex
file to set up port configuration for Heroku.
Heroku assigns a port through environment variable PORT. We need to get that port number through System.get_env("PORT")
so that our application can run on Heroku. if
clause in get_port/0
is there to provide port number when we would like to run our application locally.
Go to the root directory of our application. Then create a Heroku app with the buildpack by running heroku create --buildpack "https://github.com/HashNuke/heroku-buildpack-elixir.git"
.
The script will build the Heroku application and also set a git remote repository called heroku. Run git push heroku master
to deploy the application to Heroku. Now your application is all set and running. Run heroku open
to open the application in your browser and check if it’s running correctly.