Controllers on vanilla plug router

Hello everyone, is it possible to dispatch a request to a specific module using plug.router? Phoenix does it using its own macros but I’d like to know how to achieve the same or at least close results using only plug.router

Hi @newton-peixoto yes there are examples of this on the first page of the plug docs, give it a whirl and we’ll be here if you run into issues!

Hello, thanks for replying. I read the doc but I’m probably missing something. The closest thing that I found was the foward macro but it fowards to another plug not to a module with implementation maybe the :do option should do it?

EDIT#

I was thinking something like this

get "/baz", do: &HelloWorld.Controller.show/1

but it did not work

The convention is to do this:

get "/baz", HelloWorld.Controller, :show

the :show atom represents the name of the controller action that will handle the incoming request.

A controller action is a specific type of function that is designed to handle a specific type of request.

Phoenix is basically a giant function on a web connection (and then socket) that is broken down into a tiny steps so controller action functions would always need an arity of at least 2: one parameter for the connection and one for any parameters that might be needed for the change to the connection.

Off the top of my head, it might be worth trying to pass in conn without using the capture operator. Also, check out these other requirements from the Plug.Router docs:

Each route receives a conn variable containing a Plug.Conn struct and it needs to return a connection, as per the Plug spec…
Each Plug.Router has a plug pipeline, defined by Plug.Builder, and by default it requires two plugs: :match and :dispatch. ``

So maybe something like this for a minimal example using only Plug.Router:

defmodule AppRouter do
  use Plug.Router

  plug :match # required by default
  plug :dispatch # required by default

  get "/baz" do
    HelloWorld.Controller.show(conn) # must accept and return a connection
  end
end

Another option is using forward. Phoenix controllers are also module plugs with MyApp.Controller.call(conn, :action)

So e.g.

defmodule AppRouter do
  use Plug.Router

  plug :match # required by default
  plug :dispatch # required by default

  forward "/baz", to: HelloWorld.Controller, init_opts: :show
end

Keep in mind that Plug.Router.forward has different options than Phoenix.Router.forward, so don’t confuse them.