恶意无效URI请求致Elixir Phoenix/Plug抛异常,如何返回4xx响应?
问题结论
Plug.Router.MalformedURIError不属于Plug原生会自动转换为4xx响应的逻辑,你需要在Phoenix应用中自行适配处理。
Plug的设计原则是将协议解析类异常直接暴露给上层应用,由开发者决定错误响应的格式和状态码,避免默认行为不符合业务预期。
修复方案
方案1:顶层捕获异常(最稳妥,适配所有Plug版本)
编写一个顶层Plug,放在Endpoint所有插件的最前面,提前捕获URI解析异常,直接返回400响应:
- 新建插件文件
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
- 在
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
相关产品推荐
相关产品推荐

