DEV Community

Cover image for How does routing work?
Daniel Widgren
Daniel Widgren

Posted on • Edited on

How does routing work?

Routing

Here I will write about routing in Nova and how it works.

When we generate a new Nova app we will have a routing file within our src directory.

The file is named in our example my_first_nova_router.erl in that file we have a function that has a list of Erlang maps that will specify and configure what rules are for an endpoint.

-module(my_first_nova_router).
-behaviour(nova_router).

-export([
         routes/1
        ]).

%% The Environment-variable is defined in your sys.config in {nova, [{environment, Value}]}
routes(_Environment) ->
    [#{prefix => "",
      security => false,
      routes => [
                 {"/", fun my_first_nova_main_controller:index/1 , #{methods => [get]}},
                 {"/heartbeat", fun(_) -> {status, 200} end, #{methods => [get]}}
                ]
      }].

Enter fullscreen mode Exit fullscreen mode

What does this routing configuration indicate?

If we run this we will see the routing tree in your shell:

$ rebar3 nova routes
Host: '_'
     ├─  /assets
        └─  _ /[...] (my_first_nova, cowboy_static:init/1)
     └─  GET / (my_first_nova, my_first_nova_main_controller:index/1)

Enter fullscreen mode Exit fullscreen mode

_Environement is a variable that is set in the config file, in dev_sys.config.src we can find {environment, dev} and for prod_sys.config.src we have {environment, prod}. In this file that we got from the start we don't care if the environment is dev or prod we will start the routes here for all environments. It could be so when we develop that we want to have some extra routes for dev environment that we don't want to have in production. Then we can add a new function for dev and add the routes.

Example:

-module(my_first_nova_router).
-behaviour(nova_router).

-export([
         routes/1
        ]).

%% The Environment-variable is defined in your sys.config in {nova, [{environment, Value}]}
routes(prod) ->
  prod();
routes(dev) ->
  prod() ++ dev().

prod() ->
  [#{prefix => "",
      security => false,
      routes => [
                 {"/", fun my_first_nova_main_controller:index/1, #{methods => [get]}},       
                 {"/heartbeat", fun(_) -> {status, 200} end, #{methods => [get]}}
                ]
      }].

dev() ->
  [#{prefix => "",
  security => false,
  routes => [
             {"/dev-tools", fun my_first_nova_dev_controller:index/1, #{methods => [get]}}
            ]
  }].
Enter fullscreen mode Exit fullscreen mode

If you run rebar3 nova routes you will see that you get same result before we added the dev routes. This is because we only show what is in production and not in your development routes.

Back to the structure of the routing:

#{prefix => "",
  security => false,
  routes => [
             {"/", fun my_first_nova_main_controller:index/1 , #{methods => [get]}},
             {"/heartbeat", fun(_) -> {status, 200} end, #{methods => [get]}}
            ]
  }
Enter fullscreen mode Exit fullscreen mode

prefix is if you want to group your routes, example if you are going to make a lot of routes for users v1/user, v1/user/USERKEY, v1/user/USERKEY/... then you can use a prefix with prefix => "/v1/user" and every route in routes field will have it as a prefix.
security here is if we want to have any security for the routes specified in this map. security takes a Erlang function, fun Module:Function/1.
routes this is a list that takes an Erlang tuple {PATH, fun Module:Function/1, #{}}. Path is the endpoint, the function with Moduleand Function will tell you what controller is used for this endpoint.

What we want to do is to add a new route to our application:

-module(my_first_nova_router).
-behaviour(nova_router).

-export([
         routes/1
        ]).

%% The Environment-variable is defined in your sys.config in {nova, [{environment, Value}]}
routes(_Environment) ->
  [#{prefix => "",
      security => false,
      routes => [
                 {"/", fun my_first_nova_main_controller:index/1 , #{methods => [get]}},
                 {"/heartbeat", fun(_) -> {status, 200} end, #{methods => [get]}},
                 {"/login", fun my_first_nova_main_controller:login/1, #{methods => [get]}}
                ]
      }].
Enter fullscreen mode Exit fullscreen mode

In the example above we have added a new route for login.

Top comments (0)