Book Image

Build Your Own Web Framework in Elixir

By : Aditya Iyengar
Book Image

Build Your Own Web Framework in Elixir

By: Aditya Iyengar

Overview of this book

Elixir's functional nature and metaprogramming capabilities make it an ideal language for building web frameworks, with Phoenix being the most ubiquitous framework in the Elixir ecosystem and a popular choice for companies seeking scalable web-based products. With an ever-increasing demand for Elixir engineers, developers can accelerate their careers by learning Elixir and the Phoenix web framework. With Build Your Own Web Framework in Elixir, you’ll start by exploring the fundamental concepts of web development using Elixir. You'll learn how to build a robust web server and create a router to direct incoming requests to the correct controller. Then, you'll learn to dispatch requests to controllers to respond with clean, semantic HTML, and explore the power of Domain-Specific Languages (DSL) and metaprogramming in Elixir. You'll develop a deep understanding of Elixir's unique syntax and semantics, allowing you to optimize your code for performance and maintainability. Finally, you'll discover how to effectively test each component of your application for accuracy and performance. By the end of this book, you'll have a thorough understanding of how Elixir components are implemented within Phoenix, and how to leverage its powerful features to build robust web applications.
Table of Contents (15 chapters)
1
Part 1: Web Server Fundamentals
4
Part 2: Router, Controller, and View
10
Part 3: DSL Design

Supervising the web server

Now that we have added a router and a handler to our web server, we can add it as a child to our supervision tree by updating the list of children in our application module. For now, I will use a hardcoded TCP port of 4040 for our server, but we will use application-level configurations to set it later in this chapter:

lib/cowboy_example/application.ex

defmodule CowboyExample.Application do
  @moduledoc false
  use Application
  @impl true
  def start(_type, _args) do
    children = [
      # Add this line
      {Task, fn -> CowboyExample.Server.start(4040) end}
    ]
    opts = [
      strategy: :one_on_one,
      name: CowboyExample.Supervisor
    ]
    Supervisor.start_link(children, opts)
  end
end

In the preceding code, we’re adding to the supervised children a Task with the function to start the Cowboy listener as an argument that eventually gets passed to Task.start_link/1. This makes sure that our web server process is part of the application’s supervision tree.

Now, we can run our web application by running the mix project with the --no-halt option:

$ mix run --no-halt

Note

Passing the --no-halt option to the mix run command makes sure that the application, along with the supervision tree, is still running even after the command has returned. This is generally used for long-running processes such as web servers.

Without stopping the previous command, in a separate terminal session, we can make a request to our web server using the cURL command-line utility with the –v option to get a verbose description of our requests and responses:

$ curl –v http://localhost:4040/
*   Trying ::1:4040...
* connect to ::1 port 4040 failed: Connection refused
*   Trying 127.0.0.1:4040...
* Connected to localhost (127.0.0.1) port 4040 (#0)
> GET / HTTP/1.1
> Host: localhost:4040
> User-Agent: curl/7.75.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 11
< content-type: text/html
< server: Cowboy
<
* Connection #0 to host localhost left intact
Hello world%

As we can see in the preceding code, we get the expected "Hello World" response along with the expected status code of 200. As mentioned in the previous section, Cowboy adds custom response headers to give us more information about how it was processed. We can also see headers for the type of server (Cowboy), content length, and content type.

We should also see an application-level log corresponding to the request in the terminal session running the mix project. The logs should look somewhat like this:

$ mix run --no-halt
20:39:43.061 [info]  Received request: %{
  bindings: %{},
  body_length: 0,
  cert: :undefined,
  has_body: false,
  headers: %{
    "accept" => "*/*",
    "host" => "localhost:4040",
    "user-agent" => "curl/7.75.0"
  },
  host: "localhost",
  host_info: :undefined,
  method: "GET",
  path: "/",
  path_info: :undefined,
  peer: {{127, 0, 0, 1}, 35260},
  pid: #PID<0.271.0>,
  port: 4040,
  qs: "",
  ref: :listener,
  scheme: "http",
  sock: {{127, 0, 0, 1}, 4040},
  streamid: 1,
  version: :"HTTP/1.1"
}

We can see that we’re logging all the details corresponding to the request including headers, the host, the URI, and the process ID of the process processing the request.

Congratulations, you have now successfully built a Hello World web server using Cowboy. Now, it’s time to add more routes to our web server.