Skip to content

Instantly share code, notes, and snippets.

@mraaroncruz
Created September 1, 2022 23:22
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mraaroncruz/55b3ba6a2e94be7d09a2b1fbe0d630da to your computer and use it in GitHub Desktop.
Save mraaroncruz/55b3ba6a2e94be7d09a2b1fbe0d630da to your computer and use it in GitHub Desktop.
A livebook with a running http server that can accept requests

Working webserver

Mix.install([
  {:plug_cowboy, "> 0.0.0"},
  {:jason, "> 0.0.0"},
  {:httpoison, "> 0.0.0"}
])

Working webserver example

Let's get a plug server running that we can interact with.

The plug server

defmodule WebhookProcessor.Endpoint do
  @moduledoc """
  A Plug responsible for logging request info, parsing request body's as JSON,
  matching routes, and dispatching responses.
  """

  use Plug.Router

  # This module is a Plug, that also implements it's own plug pipeline, below:

  # Using Plug.Logger for logging request information
  plug(Plug.Logger)
  # responsible for matching routes
  plug(:match)
  # Using Poison for JSON decoding
  # Note, order of plugs is important, by placing this _after_ the 'match' plug,
  # we will only parse the request AFTER there is a route match.
  plug(Plug.Parsers, parsers: [:json], json_decoder: Jason)
  # responsible for dispatching responses
  plug(:dispatch)

  # A simple route to test that the server is up
  # Note, all routes must return a connection as per the Plug spec.
  get "/ping" do
    send_resp(conn, 200, "pong!")
  end

  # Handle incoming events, if the payload is the right shape, process the
  # events, otherwise return an error.
  post "/events" do
    {status, body} =
      case conn.body_params do
        %{"events" => events} -> {200, process_events(events)}
        _ -> {422, missing_events()}
      end

    send_resp(conn, status, body)
  end

  defp process_events(events) when is_list(events) do
    # Do some processing on a list of events
    Jason.encode!(%{response: "Received Events!"})
  end

  defp process_events(_) do
    # If we can't process anything, let them know :)
    Jason.encode!(%{response: "Please Send Some Events!"})
  end

  defp missing_events do
    Jason.encode!(%{error: "Expected Payload: { 'events': [...] }"})
  end

  # A catchall route, 'match' will match no matter the request method,
  # so a response is always returned, even if there is no route to match.
  match _ do
    send_resp(conn, 404, "oops... Nothing here :(")
  end
end

Start the server

Plug.Cowboy.shutdown(WebhookProcessor.Endpoint.HTTP)
Plug.Cowboy.http(WebhookProcessor.Endpoint, [], port: 4040)

Stop the server

Plug.Cowboy.shutdown(WebhookProcessor.Endpoint.HTTP)

Making requests

host = "http://127.0.0.1:4040"
payload = %{events: [%{name: "Sommerfest"}]}

with {:ok, %{body: body}} <-
       HTTPoison.post(host <> "/events", payload |> Jason.encode!(), [
         {"Content-Type", "application/json"}
       ]) do
  Jason.decode!(body)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment