2017-05-07 47 views
2

我正在使用Elixir编写的Phoenix/phx API上工作,并且我试图使用Postman测试JSON API的功能。我正在向API发送JSON数据,希望能够创建一个新用户,但是phx正在给我提供以下错误信息。如何正确地将JSON数据发送到phx phoenix API

Phoenix.ActionClauseError at POST /api/users 

不知道问题出在哪里,所以我会张贴路由器和phx项目的控制器。

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 

整个项目可以发现here 任何和所有帮助将大大赞赏。

我将数据发送到具有以下邮差设置的API, postman settings

下完整的错误消息,

[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 
+0

您可以发布完整的错误信息?另外,您是否拥有Postman请求中的Content-Type等? – Dogbert

+0

好的,给我一分钟。我将内容类型设置为JSON(application/json) – Chris

+2

您的数据应该如下所示:'{“user”:{“username”:...,...}}'。 – Dogbert

回答

2

由于您使用从"user"键内的地图数据,你需要把所有的字段中请求的"user"项下,这样的:

{ 
    "user": { 
    "username": "foo", 
    "email": "[email protected]", 
    "password": "password" 
    } 
} 
1

在你的控制你的模式匹配

"user" => user_params 

因此,您必须将用户参数置于用户密钥下:

"user": { 
    "email": "[email protected]", 
    ... 
}