Can I Dynamically Change the Controller and Action from a Module Plug in a Pipeline?

Sort of an awkwardly worded question in the subject, but let me try to explain the background and see if anyone has ideas or even a different approach.

I’m using the Twilio webhooks and I created a route for it to hit. It can only accept the one route. Let’s call that route /api/sms. Twilio can POST to it, it resolves to the SmsController, standard fare.

What I’d like to be able to do is: add a Plug to my api pipeline that, based on the body of the message received from Twilio, determines what controller/action it should actually resolve to. leaving /api/sms as kind of a gateway for Twilio to hit, but that’s it.

A very basic concrete example might be:

  1. If the body of the Twilio message is “Yes”, then it would set the controller to AttendeeController and the action to create
  2. If the body of the Twilio message is “No”, then it would set the controller to AttendeeController and the action to delete

That way I can keep the separation and structure of different controllers/actions, rather than have to keep the conditional logic in the SmsController.

I tried playing with put_private and setting :phoenix_controller and :phoenix_action but anything I set ended up getting overwritten by the time the pipeline was finished doing its work. Using the Controller redirect didn’t work either since it just returned that “redirecting” html as part of the 302.

Is this kind of thing even possible to pull off? or is there a better/more phoenix-like way to approach it?

thanks!

I would move the logic outside of the controller …

def post(%{assings: %{user_id: user_id}} = conn, params) do
  resp = Attendee.handle(user_id, params)
  send_resp(conn, 200, resp)
end

where Attendee.handle might look like this

def handle(user_id, %{"message" => "Yes"}) do
  # do stuff
end

I would do it this way because the actions in phoenix controllers seem to map to http verbs, and it seems strange to me to change them based on the body of the http request.

One way of doing it may be by adding a plug to your endpoint and prefixing your path with something based on the params similar to https://github.com/phoenixframework/phoenix/issues/489