You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Elixir的Plug.Parsers无法解析JSON,body_params始终为空

问题:使用Elixir + Plug构建Github Webhook端点时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:43:31