(UndefinedFunctionError)尝试登录phx / elixir API时

时间:2017-05-10 21:52:17

标签: json elixir phoenix-framework

我使用Elixir编写的phoenix框架构建API。我现在可以使用Postman创建一个用户的应用程序。 API会发回201响应。

但是,当我尝试使用新创建的用户登录时,API正在发送500响应。

我得到以下的堆栈跟踪,

[info] Running KegCopRAPI.Web.Endpoint with Cowboy using http://0.0.0.0:4000
[info] POST /api/users
[debug] Processing with KegCopRAPI.Web.UserController.create/2
  Parameters: %{"user" => %{"email" => "chris@example.com", "password" => "[FILTERED]", "username" => "chris"}}
  Pipelines: [:api]
[debug] QUERY OK db=2.8ms
INSERT INTO "accounts_users" ("email","encrypted_password","username","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" ["chris@example.com", "$2b$12$t1MvizA5fNhSvCald/jctedwvvtlI0jbY/s4W75dD/YwKiaJmZYXS", "chris", {{2017, 5, 10}, {21, 20, 28, 896254}}, {{2017, 5, 10}, {21, 20, 28, 903416}}]
[info] Sent 201 in 434ms
[info] OPTIONS /api/sessions
[info] Sent 204 in 37µs
[info] POST /api/sessions
[debug] Simple CORS request from Origin 'http://localhost:3000' is allowed
[info] Sent 500 in 16ms
[error] #PID<0.392.0> running KegCopRAPI.Web.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /api/sessions
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function KegCopRAPI.Web.SessionController.init/1 is undefined (module KegCopRAPI.Web.SessionController is not available)
        KegCopRAPI.Web.SessionController.init(:create)
        (kegcopr_api) lib/kegcopr_api/web/router.ex:1: anonymous fn/1 in KegCopRAPI.Web.Router.__match_route__/4
        (phoenix) lib/phoenix/router.ex:277: Phoenix.Router.__call__/1
        (kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.plug_builder_call/2
        (kegcopr_api) lib/plug/debugger.ex:123: KegCopRAPI.Web.Endpoint."call (overridable 3)"/2
        (kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /opt/elixir/kegcopr_api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

session_controller.ex 如下所示,

defmodule KegCopRAPI.SessionController do
  use KegCopRAPI.Web, :controller
  # Note: the below statement squelched the warning about not finding the Repo.
  alias KegCopRAPI.Repo

  def create(conn, params) do
    case authenticate(params) do
      {:ok, user} ->
        new_conn = Guardian.Plug.api_sign_in(conn, user, :access)
        jwt = Guardian.Plug.current_token(new_conn)

        new_conn
        |> put_status(:created)
        |> render("show.json", user: user, jwt: jwt)
      :error ->
        conn
        |> put_status(:unauthorized)
        |> render("error.json")
    end
  end

  def delete(conn, _) do
    jwt = Guardian.Plug.current_token(conn)
    Guardian.revoke!(jwt)

    conn
    |> put_status(:ok)
    |> render("delete.json")
  end

  def refresh(conn, _params) do
    user = Guardian.Plug.current_resource(conn)
    jwt = Guardian.Plug.current_token(conn)
    {:ok, claims} = Guardian.Plug.claims(conn)

    case Guardian.refresh!(jwt, claims, %{ttl: {30, :days}}) do
      {:ok, new_jwt, _new_claims} ->
        conn
        |> put_status(:ok)
        |> render("show.json", user: user, jwt: new_jwt)
      {:error, _reason} ->
        conn
        |> put_status(:unauthorized)
        |> render("forbidden.json", error: "Not authenticated")
    end
  end

  def unauthenticated(conn, _params) do
    conn
    |> put_status(:forbidden)
    |> render(KegCopRAPI.SessionView, "forbidden.json", error: "Not Authenticated")
  end

  defp authenticate(%{"email" => email, "password" => password}) do
    user = Repo.get_by(KegCopRAPI.User, email: String.downcase(email))

    case check_password(user, password) do
      true -> {:ok, user}
      _ -> :error
    end
  end

  defp check_password(user, password) do
    case user do
      nil -> Comeonin.Bcrypt.dummy_checkpw()
      _ -> Comeonin.Bcrypt.checkpw(password, user.password_hash)
    end
  end
end

非常感谢任何和所有帮助。

1 个答案:

答案 0 :(得分:1)

在第一个代码段中,您可以看到您的路由器无法找到KegCopRAPI.Web.SessionController,但您有KegCopRAPI.SessionController

最近在Phoenix v1.3.0-rc.0中引入了这个Web命名空间,以强调您正在改变应用程序的Web层。

此外,您的控制器代码有效,但您可以使用with子句和action_fallback宏来调整它以使Phoenix 1.3更新。