Cooking Up an API Using Maru in Elixir

Words
460
Reading
3 min
Listen
Play
9y

Introduction

Application programming interfaces (APIs) are common tools to enable developers to deal with different types of data. Companies use APIs internally to handle lots of processes such as dealing with customer data, working with company analytics, as well as creating their software products.

Cooking an API

Enter Maru a REST-like framework for Elixir

Maru is a REST-like framework for Elixir which enables developers to build expressive APIs. Maru includes many useful features for API development such as versioning, routing, parameters, and middleware. In this tutorial we will create a simple recipe API which will return the ingredients to create various food items such as cake, apple pie, and salad.

Setting up the project

To get started with a basic Maru project follow the steps on the official Maru website to get started with a basic project. You can also git clone our Maru starter here.

Routes with Maru

Here is an example of a very simple GET index route created with Maru:

get do
    json(conn, %{ hello: :world })
end

This route is indicating that the an object containing hello as a key and the atom :world as a value returns upon making a request to the '/' route. The route location can be modified simply by adding the route after the get. Let's write a route which will return all the food items we can get a recipe for.

defmodule MaruCooking.Router.Homepage do
  use Maru.Router
  @moduledoc """
    This is a simple router created with Maru
  """
  @foodItems %{ results: [:cheese_pizza,
                           :cake,
                           :caesar_salad,
                           :cheese_burger,
                           :omelet,
                           :grilled_cheese,
                           :breadsticks,
                           :tiramisu,
                           :crostini,
                           :sicilian_spaghetti ]}
  # :all refers to the /all route this route is accessible via localhost:8880/all
  get :all do
    json(conn, @foodItems)
  end
end

Route parameters

Maru also has built-in parameter validation, and types built in. Take for example:

params do
  requires :item, type: Atom
end
get :ingredients do
  json(conn, MaruCooking.FoodData.ingredients(params[:item]))
end

The above example is for the route "/ingredients" and accepts a query parameter called item which is typed as an Atom. Maru supports many parameters such as: String, Integer, Float, Boolean, CharList, Atom, File, Json, Base64.

Ingredients
In this API users can get ingredients for different items defined on the menu.

Post requests

In addition to get requests Maru also supports creation of post routes:

params do
  requires :item, type: Atom
end
post :eat do
  json(conn, MaruCooking.FoodData.eat(params[:item]))
end

Middleware

Maru also supports adding custom middleware. This is useful for example, if you have any custom before route authentication steps or are doing any data initialization. In our example we're going to keep it simple and just print "Asking the head chef."

defmodule Before do
  use Maru.Middleware

  def call(conn, _opts) do
    IO.puts "Asking the head chef..."
    conn
  end
end

We also have to plug in the Before middleware into the API module as below:

defmodule MaruCooking.API do
  use Maru.Router

  plug Plug.Parsers,
    pass: ["*/*"],
    json_decoder: Poison,
    parsers: [:urlencoded, :json, :multipart]

  plug Before
  mount MaruCooking.Router.Homepage
  ...

Now when we make a request to the API such as http://localhost:8000/all it should print "Asking the head chef..." before every request.

Conclusion

Hopefully this has been a good short introduction to how to use Maru, in addition to the features above Maru also supports versioning, exceptions, and useful built-in testing functionality. Maru can also be used in addition to Elixir's Phoenix web framework in order to make it easier to develop web applications which I will cover in a future post.

Thanks for reading!

If you enjoyed this post please check out our blog at the ElixirLuthier

Cooking Up an API Using Maru in Elixir | Ecency