Phoenix controller action that allows passthrough on nil

I am trying to create a Phoenix controller action that allows conn to fall through action if the parameter is not matched by a query.

i.e. if there is no user the conn passes through this action and gets caught by another controller

I am getting an error 500.

What am I missing?

def pass_action(conn, %{"id" => id}) do
     user = Repo.get_by(User, slug: id)
     if user != nil do
        user = Repo.get_by!(User, slug: id)
        render(conn, "show.html",
          user: user)
      else
         conn
      end
end

this status 500

00:20:16.059 [error] #PID<0.23653.0> running WwwAppCom.Web.Endpoint (connection #PID<0.21719.0>, stream id 13) terminated
Server: local.app.com:4000 (http)
Request: GET /usr
** (exit) an exception was raised:
    ** (Plug.Conn.NotSentError) a response was neither set nor sent from the connection
        (phoenix 1.5.8) lib/phoenix/endpoint/cowboy2_handler.ex:110: Phoenix.Endpoint.Cowboy2Handler.maybe_send/2
        (phoenix 1.5.8) lib/phoenix/endpoint/cowboy2_handler.ex:66: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.8.0) /deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.8.0) /deps/cowboy/src/cowboy_stream_h.erl:300: :cowboy_stream_h.execute/3
        (cowboy 2.8.0) /deps/cowboy/src/cowboy_stream_h.erl:291: :cowboy_stream_h.request_process/3
        (stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Hi,

In a controller, you need to send a response back to the client. For example, your show.html template, a 404, a redirect, etc.

If I understand correctly you would want to use a redirect: redirect(conn, to: "/your-other-controller") instead of just conn.

I hope it fixes your issue.

That’s not possible with the existing router implemenations. Once a controller was matched by the router the request is neither going back into the router, nor could the router match a later controller, as routers work with pattern matching behind the scenes. The beam does not expose means of “skipping” such a match.

I believe you can accomplish what you want with a fallback controller: Phoenix.Controller — Phoenix v1.5.8

thanks @matthieuchabert @LostKobrakai @axelson

I will investigate this very helpful information

1 Like