404 Error Handling Inside Plug?

let say i have routes like follow
web routes:
http://localhost:4000/department/:id/show
http://localhost:4000/department/:dept_id/user/:user_id
api routes:
http://localhost:4000/api/v1/department/:id/show
http://localhost:4000/api/v1/department/:dept_id/user/:user_id
and my module plug looks like

def call(%Plug.Conn{ params: %{ "dept_id" => dept_id } } = conn, _params) do
  logged_in_user = Guardian.Plug.current_resource(conn)
  result = MemberRepo.findUserBelongsToDept(logged_in_user, dept_id)
  case result do
    {:ok, 1} ->
      conn #user belongs to group continue
    {:ok, 0} ->
      IO.puts "#{conn}"
      conn
      |> put_status(404)

    {:error, error}->
      conn
end

On those routes which i mentioned above i was checking whether the user belongs to the department or not using above plug. if not it returns {:ok, 0}

i want to render 404.html for webpage and json response for api calls within the plug , how can i achieve this?

Easiest way is to call the error view render function with whatever code you want then halt() the pipeline. :slight_smile:

Probably more correct ways, but that would work.

How can i check its halted or not , currently inside the call/2 i am doing like follow

    body = "oops not found"
    conn
    |> put_resp_content_type("application/json")
    |> send_resp(404, body)
    |> halt

You could write a controller test that looks something like the following

test "this thing halts", %{conn: conn} do
  conn = get(conn, some_path(conn, :index)
  assert conn.halted
end
1 Like

this is the right answer :slight_smile:

def call(conn, _) do
  case logics(...) do
    :ok -> conn  
    :error ->
      conn
      |> Phoenix.Controller.render(MyApp.Web.ErrorView, :"404")
      |> halt()
  end
end

Passing an atom to Phoenix.Controller.render will handle the content negation and render the html/json/etc template.

10 Likes

when i am trying to pass halt in pipes like follow

conn
|> Phoenix.Controller.render(XXXX.Api.V1.ErrorView, :“404error”)
|> halt()

it continues to call another plug, why doesn’t it work, ?

Mistake from my side only, this code works now :relaxed:

 conn = conn
            |>  Phoenix.Controller.render(XXXX.Api.V1.ErrorView, :"404error")
            |>  halt()
2 Likes