当请求到达我的路由器时,我收到此错误OPTIONS "/products"
错误
14:45:33.433 [error] #PID<0.339.0> running Api.Router terminated
Server: 192.168.20.3:4000 (http)
Request: OPTIONS /products
** (exit) an exception was raised:
** (Poison.EncodeError) unable to encode value: {:brand, {"can't be blank", [validation: :required]}}
(poison) lib/poison/encoder.ex:383: Poison.Encoder.Any.encode/2
(poison) lib/poison/encoder.ex:259: anonymous fn/3 in Poison.Encoder.List.encode/3
(poison) lib/poison/encoder.ex:260: Poison.Encoder.List."-encode/3-lists^foldr/2-1-"/3
(poison) lib/poison/encoder.ex:260: Poison.Encoder.List.encode/3
(poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3
(poison) lib/poison/encoder.ex:228: Poison.Encoder.Map."-encode/3-lists^foldl/2-0-"/3
(poison) lib/poison/encoder.ex:228: Poison.Encoder.Map.encode/3
(poison) lib/poison/encoder.ex:227: anonymous fn/4 in Poison.Encoder.Map.encode/3
显示在网络请求期间在前端捕获的错误的图像:
从上图来看,产品 JSON 对象似乎确实被发送了,因此由于某种原因,它没有正确地将 http post 正文映射到 elixir 变更集。
连接日志:
Interactive Elixir (1.4.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> %{}
%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{},
before_send: [], body_params: %{},
cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
host: "192.168.20.3", method: "OPTIONS", owner: #PID<0.339.0>, params: %{},
path_info: ["products"], path_params: %{}, peer: {{192, 168, 20, 3}, 63793},
port: 4000,
private: %{plug_route: #Function<1.14347947/1 in Api.Router.do_match/4>},
query_params: %{}, query_string: "", remote_ip: {192, 168, 20, 3},
req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
req_headers: [{"host", "192.168.20.3:4000"}, {"connection", "keep-alive"},
{"access-control-request-method", "POST"}, {"origin", "http://evil.com/"},
{"user-agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/
537.36"},
{"access-control-request-headers", "content-type,x-requested-with"},
{"accept", "*/*"}, {"referer", "http://localhost:8081/debugger-ui"},
{"accept-encoding", "gzip, deflate, sdch"},
{"accept-language", "en-GB,en-US;q=0.8,en;q=0.6"}], request_path: "/products",
resp_body: nil, resp_cookies: %{},
resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
status: nil}
%Api.Product{__meta__: #Ecto.Schema.Metadata<:built, "products">, brand: nil,
description: nil, id: nil, image: nil, name: nil, numberOfVotes: nil,
rating: nil}
路由器.ex
defmodule Api.Router do
use Plug.Router
if Mix.env == :dev do
use Plug.Debugger
end
plug :match
plug Plug.Parsers, parsers: [:json],
pass: ["application/json"],
json_decoder: Poison
plug :dispatch
get "/favicon.ico" do
# Api.Repo.getCategories(conn)
end
get "/categories/" do
Api.Repo.getCategories(conn)
end
options "/categories/" do
Api.Repo.getCategories(conn)
end
post "/products" do
Api.Repo.insertProduct(conn, conn.body_params)
end
options "/products" do
IO.puts inspect conn.body_params
Api.Repo.insertProduct(conn, conn.body_params)
end
get "/products" do
Api.Repo.insertProduct(conn, conn.body_params)
end
end
在 repo.ex
def insertProduct(conn, product) do
IO.inspect(conn)
changeset = Api.Product.changeset(%Api.Product{}, product)
errors = changeset.errors
valid = changeset.valid?
case insert(changeset) do
{:ok, product} ->
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{
successs: "success"
}))
{:error, changeset} ->
conn
|> put_resp_content_type("application/json")
|> send_resp(500, Poison.encode!(%{
failure: changeset
}))
end
end
产品.ex
defmodule Api.Product do
use Ecto.Schema
@derive {Poison.Encoder, only: [:name, :brand, :description, :image, :rating, :numberOfVotes]}
schema "products" do
field :name, :string
field :brand, :string
field :description, :string
field :image, :string
field :rating, :integer
field :numberOfVotes, :integer
end
def changeset(product, params \\ %{}) do
product
|> Ecto.Changeset.cast(params, [:name, :brand, :description, :image, :rating, :numberOfVotes])
|> Ecto.Changeset.validate_required([:name, :description, :brand])
end
end