Is there a way to insert plugs after the router but in front of the controller actions?

I want to add an interceptor (plug) that is controller/action aware. As far as I know, it’s the router that calls the controller actions, so if I add my plug after the router, the plug can’t prevent the actions being called, but if I insert it before the router, then I can’t get the controller module or the action name in the plug.

I know it’s doable by overriding Phoenix.Controller.action/2 with some metaprogramming magic, but I don’t want to do this because action/2 may be further overridden in the controller modules, and I don’t know what will happen if it is overridden twice and calls super in any of the implementations.

Is there a more clean way to achieve my goal?

1 Like

Nevermind. I found that I can add the plug in the MyAppWeb.controller/0, inside the quote block.

3 Likes

I believe you can also add plugs directly in the controller module, if you do not want to define the plug for all your controllers.

See https://hexdocs.pm/phoenix/Phoenix.Controller.html#module-plug-pipeline

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  plug :authenticate, usernames: ["jose", "eric", "sonny"] when action in [:show, :edit]

  defp authenticate(conn, options) do
  ...
4 Likes

Yes, but I’m lazy :sunglasses: