How to access `conn` from different module?

import Plug.Conn would only import the functions inside the Plug.Conn module, not the conn struct from a request.

What you probably want to do is create a “context” plug like here where you can add the ip address to the returned context, such that your resolve function would become

resolve fn _, %{context: %{current_user: current_user, remote_ip: remote_ip}} -> 
  ...
end

The context plug would probably look like this

defmodule YourAppName.Web.Context do
  @behaviour Plug
  import Plug.Conn

  def init(opts) do
    opts
  end

  def call(conn, _opts) do
    case build_context(conn) do
      {:ok, context} ->
        put_private(conn, :absinthe, %{context: context})
      {:error, reason} ->
        conn
        |> send_resp(403, reason)
        |> halt()
      _ ->
        conn
        |> send_resp(400, "Bad Request")
        |> halt()
    end
  end


  # Return the current user context based on the authorization header
  # and remote ip address
  defp build_context(%{req_readers: req_readers, remote_ip: remote_ip}) do
    with "Bearer " <> token <- :proplists.get_value("authorization", req_readers),
         {:ok, current_user} <- authorize(token) do
      {:ok, %{current_user: current_user, remote_ip: remote_ip}}
    end
  end
  
  defp authorize(token) do
    # ... your auth logic
  end
end

Note that remote_ip might be “wrong” if you are behind a load balancer.

2 Likes