捕获具有无效端口范围的 HTTPoison 错误

Catching HTTPoison errors with invalid port range

遇到传递给get的url包含无效端口的情况

iex> HTTPoison.get("http://example.com:650000")

** (FunctionClauseError) no function clause matching in :inet_tcp.do_connect/4
   (kernel) inet_tcp.erl:113: :inet_tcp.do_connect({127, 0, 0, 1}, 650000, [{:packet, :raw}, {:active, false}, :binary], 8000)
   (kernel) gen_tcp.erl:185: :gen_tcp.try_connect/6
   (kernel) gen_tcp.erl:163: :gen_tcp.connect/4

看来我无法catch/rescue摆脱这种情况。

使用Kernel.SpecialForms.try/1.

try do
  HTTPoison.get("http://example.com:650000")
rescue
  e in [FunctionClauseError] ->
    IO.inspect(e, label: "Error")
    nil
end

#⇒ Error: %FunctionClauseError{...}

深入挖掘后,错误似乎是因为您使用的端口号大于最大可接受值。

端口应该在0..65535范围内,如果我们查看抛出异常的函数的源代码,我们可以注意到以下内容:

do_connect(Addr = {A,B,C,D}, Port, Opts, Time)
  when ?ip(A,B,C,D), ?port(Port)

我找不到 ?port 的来源,但我确定它会检查端口是否在范围内(非负且小于 65535)。

现在您无法处理错误的原因是因为在某些时候调用了 exit() 并且 process exit 应该处理得有点不同:

try do
  result = HTTPoison.get "http://example.com:6500000"
catch
  :exit, reason -> reason
end

您遇到了 HTTPoison 库未处理并直接传播到您的应用程序的错误,因为 exit 消息被传播,除非退出是 trapped.

PS:除非别无选择,否则不应在应用程序中处理此类错误。