Http Server in Elixir

Here’s the translation of the HTTP Server example from Go to Elixir, formatted in Markdown for Hugo:

defmodule HttpServer do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/hello" do
    send_resp(conn, 200, "hello\n")
  end

  get "/headers" do
    headers = conn.req_headers
    |> Enum.map(fn {name, value} -> "#{name}: #{value}" end)
    |> Enum.join("\n")

    send_resp(conn, 200, headers)
  end

  match _ do
    send_resp(conn, 404, "Not Found")
  end

  def start_server do
    {:ok, _} = Plug.Cowboy.http(__MODULE__, [], port: 8090)
    IO.puts "Server running on http://localhost:8090"
    :timer.sleep(:infinity)
  end
end

In Elixir, we can create a basic HTTP server using the Plug library, which provides a specification for composable modules in web applications. Here’s a breakdown of the code:

  1. We define a module HttpServer that uses Plug.Router, which gives us routing capabilities.

  2. The plug :match and plug :dispatch lines set up the router to match incoming requests and dispatch them to the appropriate handlers.

  3. We define two routes:

    • /hello: This route simply responds with “hello\n”.
    • /headers: This route reads all the HTTP request headers and echoes them in the response body.
  4. The match _ catch-all route handles any requests that don’t match the defined routes.

  5. The start_server function starts the HTTP server using Plug.Cowboy, which is an adapter that allows Plug to run on the Cowboy web server.

To run the server:

HttpServer.start_server()

You can then access the server:

$ curl localhost:8090/hello
hello

$ curl localhost:8090/headers
user-agent: curl/7.68.0
accept: */*

In Elixir, we don’t need to explicitly register handlers with routes as we do in some other languages. Instead, the routing is defined directly in the module using the DSL provided by Plug.Router.

The concept of handlers in Elixir is similar, but it’s more integrated into the language’s functional paradigm. Each route definition essentially acts as a handler, processing the conn (connection) struct and returning a modified version of it.

This example demonstrates how to create a basic HTTP server in Elixir, showcasing routing, request handling, and starting the server. The implementation is concise and leverages Elixir’s strengths in building concurrent, fault-tolerant network applications.