Api Rest With Cowboy

Jan 9 2019

Table Of Contents

  • Setup project
  • Application entrypoint
  • Cowboy files structure
  • Running it
  • At Elixir world the well know framework Phoenix is the main tool to develop the client side interface in any project. This framework allows us to develop complex real-time web systems simply with a lot of integrated features such as websockets. But in the case of just pretending to build a simple api rest a good option is to use the Cowboy library, which makes quite more lightweight the final application than using Phoenix.

    In this post I will expose how to build a simple Rest Api Service with plug_cowboy. This library makes even easier to use the Cowboy library, which is native from Erlang.

    The code of this post is availabe at this github repository.

    Setup project

    Create New project with Elixir

    mix new cowboy_example

    Add cowboy dependency at mix.exs

      defp deps do
        [
          {:plug_cowboy, "~> 2.0"}
        ]
      end

    Let's get and compile this dependency:

    mix deps.get && mix deps.compile

    Application entrypoint

    Let's use the lib/cowboy_rest.ex file as application entrypoint for the supervision tree. We need to indicate this on our mix.exs file:

    And set lib/cowboy_rest.exs as an application module so his content will be:

    defmodule CowboyRest do
      use Application
    
      def start(_type, _args) do
        children = [
        # No childrent yet
        ]
    
        opts = [strategy: :one_for_one]
        Supervisor.start_link(children, opts)
      end
    end

    We will create the folder lib/cowboy_rest where submodules will be included. In our case the only submodule will be the web one at lib/cowboy_rest/web.

    Cowboy files structure

    At this point we can start working on Cowboy on the Web submodule. We will need:

    • lib/cowboy_rest/web/supervisor: The module defined in this file will be the Supervisor of the Web submodule. At start it will launch the http_listener that behaves as entrypoints for all the requests.
    defmodule CowboyRest.Web.Supervisor do
      @moduledoc false
      use Supervisor
    
       def start_link(_arg, _opts) do
         Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
       end
    
       def init(_arg) do
         children = [
           worker(CowboyRest.Web.HttpListener, [[], []])
         ]
    
         supervise(children, strategy: :one_for_one)
       end
     end
    • lib/cowboy_rest/http_listener: This file will keep the routing to the api Rest Handler functions. This will be also in charge of launching Cowboy Listener at start.
    defmodule CowboyRest.Web.HttpListener do
      alias CowboyRest.Web.Handler
      alias Plug.Cowboy
      require Logger
    
      def start_link(_state, _opts) do
        Logger.info ("API Rest is working ...")
        options = [
          port: 4000,
          dispatch: [ { host(), routes() } ],
        ]
        Cowboy.http(__MODULE__, [], options)
      end
    
      def host(), do: :_
    
      def routes() do
        [
          {"/cowboy_rest/[...]", Cowboy.Handler, { Handler, [] }},
        ]
      end
    end
    • lib/cowboy_rest/rest_handler: It is a Rest Handler in charge of handling and answering the incoming requests.
    defmodule CowboyRest.Web.Handler do
      use Plug.Router
      require Logger
    
      plug :match
      plug :dispatch
    
      @content_type_header_key    "content-type"
      @html_header_value          "text/html"
      @entrypoint                 "/cowboy_rest/"
    
      get @entrypoint <> "/welcome" do
        Plug.Conn.fetch_query_params(conn) # populates conn.params
        |> put_resp_header(@content_type_header_key, @html_header_value)
        |> send_resp(200, "Welcome to CowboyRest Service")
      end
    
     end

    But in order to launch this submodule we need to launch our new Web supervisor from the application root, so the file ib/cowboy_rest.exs should look like this:

    defmodule CowboyRest do
      use Application
    
      def start(_type, _args) do
        children = [
        # No childrent yet
        ]
    
        Supervisor.start_link(children, [])
      end
    end
    

    Running it

    Now if we run the application with iex -S mix, we can try a http request trough the command line with curl:

    > curl localhost:4000/cowboy_rest/welcome
    Welcome to Cowboy Rest Services

    We can see how it is really easy to have a lightweigth API Rest application on elixir using Cowboy.