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

恶意无效URI请求致Elixir Phoenix/Plug抛异常,如何返回4xx响应?

问题结论

Plug.Router.MalformedURIError不属于Plug原生会自动转换为4xx响应的逻辑,你需要在Phoenix应用中自行适配处理。
Plug的设计原则是将协议解析类异常直接暴露给上层应用,由开发者决定错误响应的格式和状态码,避免默认行为不符合业务预期。

修复方案

方案1:顶层捕获异常(最稳妥,适配所有Plug版本)

编写一个顶层Plug,放在Endpoint所有插件的最前面,提前捕获URI解析异常,直接返回400响应:

  1. 新建插件文件 lib/your_app/plugs/catch_malformed_uri.ex
defmodule YourApp.Plugs.CatchMalformedURI do
  @behaviour Plug
  import Plug.Conn

  @impl true
  def init(opts), do: opts

  @impl true
  def call(conn, _opts) do
    try do
      # 执行后续插件逻辑
      conn
    rescue
      _e in Plug.Router.MalformedURIError ->
        conn
        |> put_status(:bad_request)
        |> put_resp_content_type("text/plain")
        |> send_resp(400, "Bad Request")
        |> halt()
    end
  end
end
  1. 在lib/your_app/endpoint.ex的最开头引入该插件:
defmodule YourApp.Endpoint do
  use Phoenix.Endpoint, otp_app: :your_app

  # 放在所有其他plug之前,优先捕获异常
  plug YourApp.Plugs.CatchMalformedURI

  # 原有其他plug配置保持不变
  # ...
end

方案2:注册异常响应(适配Phoenix 1.5+)

如果你的Phoenix版本高于1.5,可以直接在应用配置中注册该异常的默认状态码,Phoenix的异常处理层会自动将其转换为400响应:
在config/prod.exs中添加配置:

config :plug, :exceptions,
  Plug.Router.MalformedURIError => [status: 400, log: :warning]

配置后不需要修改其他代码,生产环境下遇到该异常会直接返回400,同时不会抛出错误到Sentry。


内容的提问来源于stack exchange,提问作者harryg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:15:01