mtrudel/bandit

plug module does not define init/1

razielgn opened this issue · 2 comments

Just upgraded a plug-only (no phoenix) small app to 1.0.0-pre.17 and getting this error when running mix test:

    ** (EXIT) an exception was raised:
        ** (RuntimeError) plug module does not define init/1
            (bandit 1.0.0-pre.17) lib/bandit.ex:315: Bandit.validate_plug/2
            (bandit 1.0.0-pre.17) lib/bandit.ex:222: Bandit.start_link/1
            (stdlib 5.0.2) supervisor.erl:420: :supervisor.do_start_child_i/3
            (stdlib 5.0.2) supervisor.erl:406: :supervisor.do_start_child/2
            (stdlib 5.0.2) supervisor.erl:390: anonymous fn/3 in :supervisor.start_children/2
            (stdlib 5.0.2) supervisor.erl:1256: :supervisor.children_map/4
            (stdlib 5.0.2) supervisor.erl:350: :supervisor.init_children/2
            (stdlib 5.0.2) gen_server.erl:962: :gen_server.init_it/2

Does not happen on mix test --preload-modules, so I guess those Kernel.function_exported? act strange.

Relevant files:

lib/myapp/application.ex

defmodule Myapp.Application do
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    opts = [strategy: :one_for_one, name: Myapp.Supervisor]

    children = [
      {Bandit, plug: Myapp.Http.Router, port: 3000}
    ]

    Supervisor.start_link(children, opts)
  end
end

lib/myapp/http/router.ex

defmodule Myapp.Http.Router do
  use Plug.Router

  # removed everything because the error is triggered even when the router is empty.

  match _ do
    send_resp(conn, 404, "not found")
  end
end

It looks like it's actually a bit more broad than just the test environment. Has to do with how Plug.Builder eagerly does init handling at compile time (the whole of Builder & Router is a whole lot of of macro magic in general).

I've got a local repro; a fix should be out shortly.

Thanks for the issue!

Ah interesting, I'm curious to see the fix. Thank you!