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.