Skip to content

Instantly share code, notes, and snippets.

@WLSF
Created June 25, 2022 19:13
Show Gist options
  • Save WLSF/b498c62ac479207cec2ffaae65a16ed7 to your computer and use it in GitHub Desktop.
Save WLSF/b498c62ac479207cec2ffaae65a16ed7 to your computer and use it in GitHub Desktop.
Web Server with Elixir
defmodule HTTPServer do
@moduledoc """
Este módulo é responsável por estabelecer uma conexão de servidor TCP
para suportar requisições HTTP.
Função principal: `start/1`
"""
defmodule Conn do
@moduledoc """
Estrutura de conexão que será usada para gerenciar nosso socket TCP.
"""
defstruct [:socket, :raw, :response]
end
@doc """
Inicia uma conexão TCP na porta indicada.
Esse socket espera receber chamadas HTTP num endpoint de health check.
Demais endpoints retornam 404.
"""
@spec start(integer()) :: {:ok, any()}
def start(port) do
IO.puts("[*:#{port}] Web Server started!")
with {:ok, socket} <- :gen_tcp.listen(port, [:binary, active: false]),
{:ok, client} <- :gen_tcp.accept(socket) do
client
|> receive_data()
|> build_http_response()
|> respond()
end
end
defp receive_data(socket) do
with {:ok, data} <- :gen_tcp.recv(socket, 0) do
IO.puts("received: #{data}")
%Conn{socket: socket, raw: data}
end
end
defp build_http_response(%Conn{socket: socket, raw: raw}) do
result =
case String.contains?(raw, "GET /health") do
true ->
%{status: 200, body: "Up and running"}
false ->
%{status: 404, body: "Not found"}
end
response = "HTTP/1.1 #{result.status} OK\nContent-Type: text/plain\nContent-Length: #{String.length(result.body)}\n\n#{result.body}"
%Conn{socket: socket, response: response}
end
defp respond(%Conn{socket: socket, response: response}) do
:gen_tcp.send(socket, response)
end
end
HTTPServer.start(8000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment