Tokumei.Router
Focused routing layer for Raxx applications
- DSL for routing incomming HTTP requests by path and method.
- Extension to the Raxx interface to provide better error handling.
- Concept of a middleware stack.
Installation
If available in Hex, the package can be installed as:
Add
tokumei_routerto your list of dependencies inmix.exs:def deps do [ {:tokumei_router, "~> 0.3.0"}, {:ace_http, "~> 0.1.2"} ] endEnsure
tokumei_routeris started before your application:def application do [applications: [:tokumei_router, :ace_http]] end
Ace.HTTP is a server that can host Raxx applications, adapters are also available for cowboy and elli.
Usage
# my_app/router.ex
defmodule MyApp.Router do
use Tokumei.Router
alias Raxx.Response
# use middleware by specifying module and configuration.
# ContentLength is included as an example.
@middleware {Tokumei.Router.ContentLength, nil}
# Define response actions inline using Raxx Helpers.
route "/hello" do
:GET -> Response.ok("Hello, World!")
end
# Match on string variables
route "/hello/:name" do
:GET ->
greeting = "Hello, #{name}!"
Response.ok(greeting)
end
# Define actions for multiple methods on a resource.
route "/users/:id" do
:GET -> UsersController.show(id, request)
:POST -> UsersController.create(id, request)
:DELETE -> UsersController.delete(id, request)
end
# Access the request and environment passed to the router
route "/users" do
:GET ->
%{page: page_number} = request.query
users_page = env.user_repo.all(page_number: page_number)
Response.ok(users_page)
end
# Handle routing errors
error %NotFoundError{request: request} do
Response.not_found("not found: #{inspect(request.path)}")
end
error %MethodNotAllowedError{allowed: allowed} do
Raxx.Response.method_not_allowed([{"allow", allowed |> Enum.join(" ")}])
end
# return custom errors
route "/sign-up" do
:POST ->
case validate_sign_up_form(request.body) do
{:ok, data} ->
Response.created()
# continue
{:error, _reason} ->
{:error, :bad_request}
end
end
error :bad_request do
Response.bad_request()
end
# Mount subapp
mount "/api", APIRouter
end
Choose a server to host the application.
Using Tokumei.Router will create a Raxx App that can be mounted using any of the adapters found in Raxx
defmodule MyApp do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
worker(Ace.HTTP, [{MyApp.Router, []}, [port: 8080]])
]
opts = [strategy: :one_for_one]
Supervisor.start_link(children, opts)
end
end
The Tokumei.Router provides a simple routing DSL that first routes on path and second on request method.
This is done so that Tokumei.Router can return the correct responses for resources that will respond to only a subset of HTTP verbs.
import Raxx.Request
assert 200 == MyApp.Router.handle_request(get("/hello"), :env)
assert 405 == MyApp.Router.handle_request(put("/hello"), :env)
assert 404 == MyApp.Router.handle_request(put("/random"), :env)