Honeybee

Disclaimer

The interface and specifics of the Honeybee API are subject to change throughout development toward version 1.0.0. Use of Honeybee in production environments can be a risk. Report any issues to the IssueTracker

What is Honeybee?

Honeybee is a router intended for microservice/SOA APIs. It can be seen as an extension of Plug.

Honeybee's key features / goals:

  • Easy to understand, Easy to read, Easy to write.
  • Small and fast.
  • Unopinionated.
  • Strict compile-time validations.

Honeybee builds further ontop of the plug interface. It takes inspiration from both the Plug router and the Phoenix router, taking the good from both routers, in an attempt to provide the best router API for building small performant scalable APIs. Honeybee offers a slim DSL for declaring routes as isolated plug pipelines. This allows developers to quickly develop versatile routers, and allows the developer to use any plug compatible libraries natively in the pipelines.

Performance

Honeybee is the fastest router in the Elixir language (based on microbenchmarking), surpassing the performance of both the Plug and Phoenix routers.

Typical routing speeds of Honeybee are in the sub microsecond range.

Benchmarking was done using Benchee. Benchmarking performance of a batch of 10 000 random requests onto 100 routes is shown.

alt text

alt text

Example

defmodule MyApp.MyRouter do
  use Honeybee
  alias MyApp.Routes

  scope "/examples" do
    get "/hello" do
      plug Routes.Example, action: :static
    end

    get "/:id" do
      plug Routes.Example, action: :param
    end

    get "/hello*glob" do
      plug Routes.Example, action: :glob
    end

    get "/*glob" do
      plug Routes.Example, action: :glob
    end
  end

  match _, "*", do: plug :not_found
  def not_found(%Plug.Conn{path: path} = conn, _opts) do
    Plug.Conn.send_resp(conn, 404, "Not Found: " <> #{path})
  end
end
defmodule MyApp.Routes.Example do
  use Honeybee.Handler

  def static(conn, _opts) do
    Plug.Conn.send_resp(conn, 200, "world")
  end

  def param(conn, _opts) do
    %{
      "id" => id
    } = conn.path_params

    Plug.Conn.send_resp(conn, 200, "Got " <> id)
  end

  def glob(conn, _opts) do
    %{
      "glob" => glob
    } = conn.path_params
  
    Plug.Conn.send_resp(conn, 200, "Globbing: " <> Enum.join(glob, "/"))
  end
end
$ curl http://localhost:8080/examples/hello
world

$ curl http://localhost:8080/examples/10
Got 10

$ curl http://localhost:8080/examples/this/will/be/globbed
Globbing: this/will/be/globbed

$ curl http://localhost:8080/examples/hello-world/whats-up
Globbing: -world/whats-up

$ curl http://localhost:8080/something/that/doesnt/exist
Not Found: /something/that/doesnt/exist

Dependencies

Honeybee depends on Plug.