Reputation: 4033
I am working on a Phoenix / phx API written using Elixir, and I am trying to test the functionality of the JSON API using Postman. I'm sending JSON data to the API to hopefully create a new user, but phx is giving me the following error.
Phoenix.ActionClauseError at POST /api/users
Not sure where the problem lies exactly, so I'll post the router and the controller for the phx project.
router.ex
defmodule KegCopRAPI.Web.Router do
use KegCopRAPI.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader, realm: "Bearer"
plug Guardian.Plug.LoadResource
end
scope "/", KegCopRAPI.Web do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
# Other scopes may use custom stacks.
scope "/api", KegCopRAPI.Web do
pipe_through :api
post "/sessions", SessionController, :create
delete "/sessions", SessionController, :delete
post "/sessions/refresh", SessionController, :refresh
resources "/users", UserController, except: [:show, :index, :new, :edit]
end
end
user_controller.ex
def create(conn, %{"user" => user_params}) do
# with {:ok, %User{} = user} <- Accounts.create_user(user_params) do
changeset = User.registration_changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, user} ->
new_conn = Guardian.Plug.api_sign_in(conn, user, :access)
jwt = Guardian.Plug.current_token(new_conn)
# conn
# |> put_status(:created)
# |> put_resp_header("location", user_path(conn, :show, user))
# |> render("show.json", user: user)
new_conn
|> put_status(:created)
|> render(KegCopRAPI.SessionView, "show.json", user: user, jwt: jwt)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(KegCopRAPI.ChangesetView, "error.json", changeset: changeset)
end
end
The entire project can be found here Any and all help would greatly be appreciated.
I'm sending data to the API with the following Postman settings,
The complete error message below,
[info] POST /api/users
[debug] Processing with KegCopRAPI.Web.UserController.create/2
Parameters: %{"email" => "[email protected]", "password" => "[FILTERED]", "username" => "foo"}
Pipelines: [:api]
[info] Sent 400 in 10ms
[debug] ** (Phoenix.ActionClauseError) could not find a matching KegCopRAPI.Web.UserController.create clause
to process request. This typically happens when there is a
parameter mismatch but may also happen when any of the other
action arguments do not match. The request parameters are:
%{"email" => "[email protected]", "password" => "password", "username" => "foo"}
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:14: KegCopRAPI.Web.UserController.create(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<1.33581574/1 in Plug.Logger.call/2>, #Function<0.72433304/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{"email" => "[email protected]", "password" => "password", "username" => "foo"}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "POST", owner: #PID<0.2357.0>, params: %{"email" => "[email protected]", "password" => "password", "username" => "foo"}, path_info: ["api", "users"], path_params: %{}, peer: {{127, 0, 0, 1}, 59852}, port: 4000, private: %{KegCopRAPI.Web.Router => {[], %{}}, :guardian_default_resource => nil, :phoenix_action => :create, :phoenix_controller => KegCopRAPI.Web.UserController, :phoenix_endpoint => KegCopRAPI.Web.Endpoint, :phoenix_format => "json", :phoenix_layout => {KegCopRAPI.Web.LayoutView, :app}, :phoenix_pipelines => [:api], :phoenix_router => KegCopRAPI.Web.Router, :phoenix_view => KegCopRAPI.Web.UserView, :plug_session_fetch => #Function<1.131660147/1 in Plug.Session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"cache-control", "no-cache"}, {"postman-token", "da608739-758b-40d7-bdef-23b3c2a63bed"}, {"content-type", "application/json"}, {"user-agent", "PostmanRuntime/3.0.11-hotfix.2"}, {"accept", "*/*"}, {"host", "localhost:4000"}, {"accept-encoding", "gzip, deflate"}, {"content-length", "76"}, {"connection", "keep-alive"}], request_path: "/api/users", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "slfdhshckenp3dinlqr22m5nlakhoaq4"}, {"access-control-allow-origin", "*"}, {"access-control-expose-headers", ""}, {"access-control-allow-credentials", "true"}, {"vary", ""}], scheme: :http, script_name: [], secret_key_base: "fIEpvi5ujSQEKgmkRpt83KiLPq068sSmvFKlWFZyNpi3nkNmUtYO24Em6cXIUblZ", state: :unset, status: nil}, %{"email" => "[email protected]", "password" => "password", "username" => "foo"})
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:1: KegCopRAPI.Web.UserController.action/2
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:1: KegCopRAPI.Web.UserController.phoenix_controller_pipeline/2
(kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.instrument/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
Upvotes: 2
Views: 3928
Reputation: 222148
Since you're using the data from the map inside the "user"
key, you need to put all the fields under the "user"
key in the request, like this:
{
"user": {
"username": "foo",
"email": "[email protected]",
"password": "password"
}
}
Upvotes: 3
Reputation: 13211
In your controller you are pattern-matching
"user" => user_params
So, you have to put the user params under the user key:
"user": {
"email": "[email protected]",
...
}
Upvotes: 1