HTTPoison.patch 上没有处理请求错误的匹配操作子句
No Matching Action Clause to Process Request error on HTTPoison.patch
从 elixir genserver 进程中,我正在执行 post_metdata 方法以将 JSON HTTP 补丁请求发送到 Phoenix 端点(在另一台服务器上)。服务器继续错误指示没有匹配子句显示 JSON link 结构未包含在基于该方法的参数中。包含 id 但不包含传递的数据有效负载。对似乎是什么问题有什么建议吗?
客户代码
defp post_metadata(metadata, webhook) do
case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json"}] do
{:ok, %HTTPoison.Response{status_code: 200} = response} ->
# Logger.debug response.body
Logger.debug "Successfully extracted and posted metadata for #{webhook}"
{:error, %HTTPoison.Error{reason: reason}} ->
Logger.warn "Unable to extract and post metadata for #{webhook}"
end
end
defp encode(metadata) do
%{
"link":
%{
"title": metadata.title,
"description": metadata.description
}
}
|> Poison.encode!
end
需要 Phoenix Controller 方法,但未匹配
def update(conn, %{"id" => id, "link" => link_params}) do
link = Repo.get!(Link, id)
changeset = Link.changeset(link, link_params)
case Repo.update(changeset) do
{:ok, link} ->
render(conn, "show.json", link: link)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Mini.ChangesetView, "error.json", changeset: changeset)
end
end
router.ex
defmodule Mini.Router do
use Mini.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 Plug.Logger, log: :debug
end
scope "/", Mini do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
scope "/api", Mini do
pipe_through :api
resources "/links", LinkController, except: [:new, :edit]
end
end
错误记录到控制台
[debug] ** (Phoenix.ActionClauseError) bad request to Mini.LinkController.update, no matching action clause to process request
(mini) web/controllers/link_controller.ex:39: Mini.LinkController.update(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<1.42492691/1 in Plug.Logger.call/2>, #Function<1.42492691/1 in Plug.Logger.call/2>, #Function<0.111727833/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "PATCH", owner: #PID<0.438.0>, params: %{"id" => "12"}, path_info: ["api", "links", "12"], path_params: %{}, peer: {{127, 0, 0, 1}, 55369}, port: 4000, private: %{Mini.Router => {[], %{}}, :phoenix_action => :update, :phoenix_controller => Mini.LinkController, :phoenix_endpoint => Mini.Endpoint, :phoenix_format => "json", :phoenix_layout => {Mini.LayoutView, :app}, :phoenix_pipelines => [:api], :phoenix_route => #Function<4.107513407/1 in Mini.Router.match_route/4>, :phoenix_router => Mini.Router, :phoenix_view => Mini.LinkView, :plug_session_fetch => #Function<1.61377594/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: [{"content-type", "application/json, application/json"}, {"user-agent", "hackney/1.6.6"}, {"host", "localhost:4000"}, {"content-length", "58"}], request_path: "/api/links/12", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "5bggaasurlj1oe027nvmv5aiek0hq3k8"}], scheme: :http, script_name: [], secret_key_base: "YfnqjmBhsSJMF/TmhK6qpMnJl7mS0tIYHk1tZ/dZUA6d7KOdv2g/AOJUfWo8sulb", state: :unset, status: nil}, %{"id" => "12"})
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.action/2
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.phoenix_controller_pipeline/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.instrument/4
(mini) lib/phoenix/router.ex:261: Mini.Router.dispatch/2
(mini) web/router.ex:1: Mini.Router.do_call/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.phoenix_pipeline/1
(mini) lib/plug/debugger.ex:123: Mini.Endpoint."call (overridable 3)"/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/billc/dev/mini/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
我已经使用 Insomnia 成功地执行了一个模拟 JSON 数据结构的请求。我将两个请求都发送到 Httpbin 并进行了比较。我能找到的唯一区别是内容类型对于 HTTPoison 发送的请求有重复的 application/json 条目。但是,我找不到任何理由或选项来防止重复值。也没有任何理由让 Phoenix 窒息。
出于无法解释的原因,HTTPoison 在 content-type header 中添加了重复的 'application/json' 值。 Plug 因具有多个 content-type 值而感到窒息。我通过在传入的 header.
末尾添加 semi-colon 解决了这个问题
case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json;"}] do
结尾 semi-colon 终止 content-type 值。 HTTPoison 仅插入单个 'application/json' 值,Plug 正常运行。
奇怪。
从 elixir genserver 进程中,我正在执行 post_metdata 方法以将 JSON HTTP 补丁请求发送到 Phoenix 端点(在另一台服务器上)。服务器继续错误指示没有匹配子句显示 JSON link 结构未包含在基于该方法的参数中。包含 id 但不包含传递的数据有效负载。对似乎是什么问题有什么建议吗?
客户代码
defp post_metadata(metadata, webhook) do
case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json"}] do
{:ok, %HTTPoison.Response{status_code: 200} = response} ->
# Logger.debug response.body
Logger.debug "Successfully extracted and posted metadata for #{webhook}"
{:error, %HTTPoison.Error{reason: reason}} ->
Logger.warn "Unable to extract and post metadata for #{webhook}"
end
end
defp encode(metadata) do
%{
"link":
%{
"title": metadata.title,
"description": metadata.description
}
}
|> Poison.encode!
end
需要 Phoenix Controller 方法,但未匹配
def update(conn, %{"id" => id, "link" => link_params}) do
link = Repo.get!(Link, id)
changeset = Link.changeset(link, link_params)
case Repo.update(changeset) do
{:ok, link} ->
render(conn, "show.json", link: link)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Mini.ChangesetView, "error.json", changeset: changeset)
end
end
router.ex
defmodule Mini.Router do
use Mini.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 Plug.Logger, log: :debug
end
scope "/", Mini do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
scope "/api", Mini do
pipe_through :api
resources "/links", LinkController, except: [:new, :edit]
end
end
错误记录到控制台
[debug] ** (Phoenix.ActionClauseError) bad request to Mini.LinkController.update, no matching action clause to process request
(mini) web/controllers/link_controller.ex:39: Mini.LinkController.update(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<1.42492691/1 in Plug.Logger.call/2>, #Function<1.42492691/1 in Plug.Logger.call/2>, #Function<0.111727833/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "PATCH", owner: #PID<0.438.0>, params: %{"id" => "12"}, path_info: ["api", "links", "12"], path_params: %{}, peer: {{127, 0, 0, 1}, 55369}, port: 4000, private: %{Mini.Router => {[], %{}}, :phoenix_action => :update, :phoenix_controller => Mini.LinkController, :phoenix_endpoint => Mini.Endpoint, :phoenix_format => "json", :phoenix_layout => {Mini.LayoutView, :app}, :phoenix_pipelines => [:api], :phoenix_route => #Function<4.107513407/1 in Mini.Router.match_route/4>, :phoenix_router => Mini.Router, :phoenix_view => Mini.LinkView, :plug_session_fetch => #Function<1.61377594/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: [{"content-type", "application/json, application/json"}, {"user-agent", "hackney/1.6.6"}, {"host", "localhost:4000"}, {"content-length", "58"}], request_path: "/api/links/12", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "5bggaasurlj1oe027nvmv5aiek0hq3k8"}], scheme: :http, script_name: [], secret_key_base: "YfnqjmBhsSJMF/TmhK6qpMnJl7mS0tIYHk1tZ/dZUA6d7KOdv2g/AOJUfWo8sulb", state: :unset, status: nil}, %{"id" => "12"})
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.action/2
(mini) web/controllers/link_controller.ex:1: Mini.LinkController.phoenix_controller_pipeline/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.instrument/4
(mini) lib/phoenix/router.ex:261: Mini.Router.dispatch/2
(mini) web/router.ex:1: Mini.Router.do_call/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.phoenix_pipeline/1
(mini) lib/plug/debugger.ex:123: Mini.Endpoint."call (overridable 3)"/2
(mini) lib/mini/endpoint.ex:1: Mini.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/billc/dev/mini/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
我已经使用 Insomnia 成功地执行了一个模拟 JSON 数据结构的请求。我将两个请求都发送到 Httpbin 并进行了比较。我能找到的唯一区别是内容类型对于 HTTPoison 发送的请求有重复的 application/json 条目。但是,我找不到任何理由或选项来防止重复值。也没有任何理由让 Phoenix 窒息。
出于无法解释的原因,HTTPoison 在 content-type header 中添加了重复的 'application/json' 值。 Plug 因具有多个 content-type 值而感到窒息。我通过在传入的 header.
末尾添加 semi-colon 解决了这个问题case HTTPoison.patch webhook, encode(metadata), [{"content-type", "application/json;"}] do
结尾 semi-colon 终止 content-type 值。 HTTPoison 仅插入单个 'application/json' 值,Plug 正常运行。
奇怪。