使用Elixir的Plug.Parsers无法解析JSON,body_params始终为空
我正尝试用Elixir和Plug构建一个接收Github JSON数据的端点,但不知道为什么body_params始终是空的。我的代码如下:
defmodule Endpoint do import Plug.Conn require Logger use Plug.Builder plug Plug.Parsers, parsers: [:json], json_decoder: Jason def init(options), do: options def call(conn, _opts) do Logger.debug inspect(conn) conn |> put_resp_content_type("text/plain") |> send_resp(200, "Welcome Github!\n") end end
先检查请求的Content-Type头
Github发送Webhook请求时,默认会把Content-Type设为application/json,但如果这个请求头缺失或者不正确,Plug.Parsers就不会触发JSON解析逻辑。你可以先在日志里确认请求头里是否包含这个字段——要是没有,要么是请求本身的问题,要么是你在其他中间件里不小心修改了请求头。确认Plug.Parsers的加载顺序
用Plug.Builder的时候,plug宏的顺序特别重要!一定要保证Plug.Parsers是在所有可能会读取请求body的插件之前被调用的——因为请求body只能被读取一次,要是之前的插件已经调用过read_body/1,那Plug.Parsers就没法再解析它了。你的代码里目前Plug.Parsers是第一个插件,这部分没问题,但之后加新插件的时候可得注意顺序。手动验证解析逻辑
你可以在call函数里手动读取body来排查问题,代码改成这样:def call(conn, _opts) do {:ok, body, conn} = read_body(conn) Logger.debug "Raw body: #{body}" Logger.debug inspect(conn.body_params) conn |> put_resp_content_type("text/plain") |> send_resp(200, "Welcome Github!\n") end如果
Raw body能输出Github发送的JSON内容,但body_params还是空,那大概率是Plug.Parsers的配置有问题。比如你有没有在mix.exs里正确添加Jason依赖?记得要加上{:jason, "~> 1.0"},并且运行mix deps.get安装依赖。别忘了Github Webhook的压缩情况
要是你在Github Webhook设置里开启了Content encoding,那Github会发送gzip压缩后的body,这时候你得把:gzip解析器加到Plug.Parsers里:plug Plug.Parsers, parsers: [:gzip, :json], json_decoder: Jason这样Plug会先解压body,再解析成JSON。
内容的提问来源于stack exchange,提问作者ngw

