Plug.Parser 不是 reading/parsing JSON 正文
Plug.Parser not reading/parsing JSON body
我正在编写一个 Elixir (1.8) + Plug_Cowboy (2.0.2) + Jason (1.1.2) 服务器。根据我从文档中得到的信息,一旦 Plug 解析器通过,我应该拥有 body_params
中的所有内容。问题是在我的例子中访问 conn.body_params
returns %Plug.Conn.Unfetched{aspect: :body_params}
。检查下面的代码:
defmodule Test.Router do
use Plug.Router
require Logger
plug :match
plug Plug.Parsers, parsers: [:json],
pass: ["application/json", "text/json"],
json_decoder: Jason
plug :dispatch
post "/test" do
Logger.debug inspect(conn.body_params)
conn
|> put_resp_content_type("text/plain")
|> send_resp(204, "Got it")
end
end
知道发生了什么事吗?
我用以下方法测试:
curl -H "Content-Type: text/json" -d "{one: 1, two: 2}" 127.0.0.1:8080/test
我试过将 :urlencoded
添加到解析器,或重新排列插件顺序,但无济于事。
Plug.Parsers.JSON
仅处理 application/json
内容类型。这就是 body_params
未被填充的原因。您的测试 JSON 也无效 - 对象 属性 名称未被引用。
curl -H "Content-Type: application/json" -d '{"one": 1, "two": 2}' 127.0.0.1:8080/test
Plug.Parsers
的 pass:
选项指示它忽略那些没有定义解析器的类型的请求(例如 text/json
在你的情况下),而不是提出一个UnsupportedMediaTypeError
,这是它通常会做的。添加该选项隐藏了错误。
您可能会发现它在开发过程中对 use
Plug.Debugger
很有用 - 它可以让您更好地了解意外情况下发生的情况。
如果出于某种原因您需要能够使用非标准 text/json
类型解析 JSON(例如,由于来自您无法控制的软件的请求),您可以定义一个该类型的新解析器刚刚结束 Plug.Parsers.JSON
并将 text/json
重写为 application/json
:
defmodule WrongJson do
def init(opts), do: Plug.Parsers.JSON.init(opts)
def parse(conn, "text", "json", params, opts) do
Plug.Parsers.JSON.parse(conn, "application", "json", params, opts)
end
def parse(conn, _type, _subtype, _params, _opts), do: {:next, conn}
end
然后将其添加到您的解析器列表中:
plug Plug.Parsers,
parsers: [:json, WrongJson],
json_decoder: Jason
现在 text/json
也可以了。
我正在编写一个 Elixir (1.8) + Plug_Cowboy (2.0.2) + Jason (1.1.2) 服务器。根据我从文档中得到的信息,一旦 Plug 解析器通过,我应该拥有 body_params
中的所有内容。问题是在我的例子中访问 conn.body_params
returns %Plug.Conn.Unfetched{aspect: :body_params}
。检查下面的代码:
defmodule Test.Router do
use Plug.Router
require Logger
plug :match
plug Plug.Parsers, parsers: [:json],
pass: ["application/json", "text/json"],
json_decoder: Jason
plug :dispatch
post "/test" do
Logger.debug inspect(conn.body_params)
conn
|> put_resp_content_type("text/plain")
|> send_resp(204, "Got it")
end
end
知道发生了什么事吗?
我用以下方法测试:
curl -H "Content-Type: text/json" -d "{one: 1, two: 2}" 127.0.0.1:8080/test
我试过将 :urlencoded
添加到解析器,或重新排列插件顺序,但无济于事。
Plug.Parsers.JSON
仅处理 application/json
内容类型。这就是 body_params
未被填充的原因。您的测试 JSON 也无效 - 对象 属性 名称未被引用。
curl -H "Content-Type: application/json" -d '{"one": 1, "two": 2}' 127.0.0.1:8080/test
Plug.Parsers
的 pass:
选项指示它忽略那些没有定义解析器的类型的请求(例如 text/json
在你的情况下),而不是提出一个UnsupportedMediaTypeError
,这是它通常会做的。添加该选项隐藏了错误。
您可能会发现它在开发过程中对 use
Plug.Debugger
很有用 - 它可以让您更好地了解意外情况下发生的情况。
如果出于某种原因您需要能够使用非标准 text/json
类型解析 JSON(例如,由于来自您无法控制的软件的请求),您可以定义一个该类型的新解析器刚刚结束 Plug.Parsers.JSON
并将 text/json
重写为 application/json
:
defmodule WrongJson do
def init(opts), do: Plug.Parsers.JSON.init(opts)
def parse(conn, "text", "json", params, opts) do
Plug.Parsers.JSON.parse(conn, "application", "json", params, opts)
end
def parse(conn, _type, _subtype, _params, _opts), do: {:next, conn}
end
然后将其添加到您的解析器列表中:
plug Plug.Parsers,
parsers: [:json, WrongJson],
json_decoder: Jason
现在 text/json
也可以了。