Plug ignoring plug.builder

taking the following implementation


defmodule TestesPay.MyRouter do
  use Plug.Router
  alias MyApp.Controllers.Referral

  plug :match
  plug :dispatch

  post "api/referral", to: Referral, init_opts: :create
defmodule MyApp.Controllers.Referral do
  use Plug.Builder

  plug MyApp.PlugServer.Plugs.CheckRequestFields,
    fields: ["alias"], 
    paths: ["api/referral"] 
  
  def init(opts), do: opts

  def call(conn, opts) do
    conn
    |> dispatch_action(opts)
  end

  defp dispatch_action(conn, :create), do: create(conn)
  defp dispatch_action(conn, :delete), do: delete(conn)

where checkrequest has the follow impl

defmodule MyApp.PlugServer.Plugs.CheckRequestFields do
  def init(options), do: options
  alias Plug.Conn

  def call(%Plug.Conn{request_path: path} = conn, opts) do
    IO.inspect('------------>')
    {:ok, body_as_json, conn} = Plug.Conn.read_body(conn, opts)
    if path in opts[:paths] do
      verify_tuple = verify_request_fields!(body_as_json, opts[:fields], MyApp.Validate.CustomRules.get_rules(conn.request_path)) ##cuidado com essa linha ao começar muitos roteamentos
      
      conn = case verify_tuple do
        {:ok, body} -> 
          conn
          |> Conn.assign(:status, 200)
          |> Conn.assign(:resp, verify_tuple)
          |> Conn.assign(:resp_body_as_json, body_as_json)
        {:error, error_body_as_json} -> 
          conn
          |> Conn.assign(:status, 400)
          |> Conn.assign(:resp, verify_tuple)
          |> Conn.assign(:resp_body_as_json, error_body_as_json)
      end
      conn
    else
      conn = Conn.assign(conn, :resp, {:error, %{"msg" => "algo deu errado em call check request fields"}})
      conn
    end
  end
... #other piece of code

I got the following output:

Request: POST /api/referral
** (exit) an exception was raised:
    ** (KeyError) key :status not found in: %{}
        (testes_pay 0.1.0) lib/my_app/controllers/controller_referral.ex:25: MyApp.Controllers.Referral.create/1
        (testes_pay 0.1.0) deps/plug/lib/plug/router.ex:246: anonymous fn/4 in TestesPay.MyRouter.dispatch/2
        (telemetry 1.3.0) c:/Users/pedro/OneDrive/Área de Trabalho/testes_pay/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
        (testes_pay 0.1.0) deps/plug/lib/plug/router.ex:242: TestesPay.MyRouter.dispatch/2
        (testes_pay 0.1.0) lib/plug_server/router.ex:1: TestesPay.MyRouter.plug_builder_call/2
        (plug_cowboy 2.7.2) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.12.0) c:/Users/pedro/OneDrive/Área de Trabalho/testes_pay/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.12.0) c:/Users/pedro/OneDrive/Área de Trabalho/testes_pay/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3

why my request isn t passing though checkrequestfields?

:wave: @henriquesati

Because you overrode the Plug.Builder’s implementations for init and call. You need to call super to call them. See Plug.Builder — Plug v1.16.1

1 Like

It isnt my intention, where I did that? the purpose is just to load checkrequest as a middleware before Controller.Referral process the request

def init(opts), do: opts

def call(conn, opts) do
  conn
  |> dispatch_action(opts)
end

these overrode Plug.Builder’s init and call. To “call” them you need to use super

def init(opts), do: {opts, super(opts)}

def call(conn, {opts, super_opts}) do
  conn
  |> super(super_opts)
  |> dispatch_action(opts)
end

Please see the docs I linked above.

ye ye I read and understood right on and was able to fix it, thanks