Build a simple api with Elixir, Plug MongoDB and Cowboy

Hassane Sow
4 min readApr 29, 2020

As I’m currently working on a personnal project that involved building a service with Elixir without using Phoenix, I first struggled to find an example that was well enough explained but I eventually understood more about Plug and Cowboy so I decided to help you guys who are in the same position.

We will build a movie api that will implement all CRUD operations, the goal is not to build a full api with authentication and all other stuffs involved but just to show how to return json response, how to deal with Mongo integration, communicating with other processes and sharing the way I organize my projects

If you are just starting with Elixir, I’ll highly suggest to visit Elixir school, I think it is the best resource available for someone who’s willing to jump into the Elixir and BEAM world.

Let’s create a new project

For the project we’ll create a supervised project which will allow us to supervise all the processes within one parent process. In order to do that, we’ll need to create a new mix project with the sup option.

mix new movie_api --sup && cd movie_api

We then need to add the dependencies we need to work with. We’ll need to install Plug and Cowboy (plug_cowboy), mongodb, poolboy and then Jason for the json encoding. You’ll need to update your dependencies by adding them in the mix.exs file and in the extra_applications list of your project.

If you have trouble reading it, click here

Adding the configuration files

I really love the mix configuration system, it’s so easy to understand it and configure. We first need to create a config folder in the root of our application. Then we’ll add three files in it: config.exs dev.exs prod.exs test.exs

The dev, prod and test files represent the configuration files for each environment of development. Their content will be added to the config file depending on which environment we are on.

API structure

We won’t have all of our logic in the same file, we will split in two folders: services repositories. As our API is only required to manage the movies, each of this folders can be replaced with a single module but we’ll keep it general here.

The repositories module will handle our interactions with the database which means that here is the only place we’ll call our database inside the project.

The services module will handle the logic of the api, it will also make sure that all the data we receive from the client is safe and correct.

The endpoints module will handle the http requests.

Let’s build the router

First we’ll add the router to the main supervisor. The supervisor is defined in lib/movie_api/application.ex file.

Defining the routes

The routes will just receive an request that they’ll pass to the service which will return a response following this patter {:code, :message} where the :code represents an HTTP code such as 200, 404, 500 and the :message represents the data we want to send back.

We will create a file named endpoints.ex which will have the following content

If you have trouble seeing it, click this link

The service module

Create a new module inside the services repository and name it movie_service.ex

Well! Now you’ve created a new module, let’s add its functions. We want it to implements the CRUD functions. Let’s add them:

if you have trouve seeing it, you can click the link here

The repository

As explained before, this module will handle all the database operations related to the movies. We first need to the connection with mongodb.

If you have trouble seeing it, click this link

Then we create a new file name movie_repository.ex in the repositories directory.

If you can’t see it well enough, click this link

As you can see, we are using :database to access to the mongo’s pid instead of using the pid directly.

At this point, the API should be working fine. Let’s add an explanation to what we just did.

The Repository

This is where all the database operations will be executed, we will just execute a query and return directly its results to the service that called it.

The service

The service is in charge of validating the data received and parsing the data into the correct format either in json or bson for the object ids. It will receive data from the router and will execute it by sending data in the right format to the repository which will send it back.

The endpoint

This is where we define our routes and will call the service to execute the client’s requests. It will analyze the response received from the service and will send a response depending on the result.

If we had to rename the repository by r , the service by s and the endpoint by e , the execution process would look like this:

request -> e -> s -> r -> s -> e -> response

Thank you for reading, I hope you enjoyed it

--

--