Marsel.V
Marsel.V

Reputation: 1044

try rescue does not does not catch an error

  def page_request(url, proxy) do
    uri = URI.parse(proxy)
    case uri.host do
      nil -> raise "Host nil! #{proxy}"
      _ ->
        options =
        case uri.scheme do
            "socks5" -> default_params() ++ [proxy: {:socks5, String.to_charlist(uri.host), uri.port}]
            _-> default_params() ++ [proxy: String.to_charlist(proxy)]
        end
        try do #36 line!
          case HTTPoison.request(:get, String.to_charlist(url), "", [], options) do
            {:ok, response} ->
              %HTTPoison.Response{headers: header, body: body} = response
              gzipped = Enum.any?(header, fn (kv) ->
                case kv do
                  {"Content-Encoding", "gzip"} -> true
                  {"Content-Encoding", "x-gzip"} -> true
                  _ -> false
                end
              end)
              case body do
                nil -> {:ok, %{}}
                _ ->
                  if gzipped do
                    {:ok, :zlib.gunzip(body)}
                  else
                    {:ok, body}
                  end
              end
            {:error, reason} ->
              {:error, reason}
          end
        rescue
          error -> {:error, error}
        end
    end
  end

I can not understand why try..rescue does not catch an error?

15:34:24.537 [error] GenServer MyWeb.Worker1 terminating
** (ArgumentError) argument error
    (kernel) gen_tcp.erl:150: :gen_tcp.connect/4
    (hackney) /home/book/my_web/deps/hackney/src/hackney_connect.erl:247: :hackney_connect.do_connect/5
    (hackney) /home/book/my_web/deps/hackney/src/hackney.erl:354: :hackney.send_request/2
    (hackney) /home/book/my_web/deps/hackney/src/hackney.erl:810: :hackney.redirect/2
    (hackney) /home/book/my_web/deps/hackney/src/hackney.erl:742: :hackney.maybe_redirect1/3
    (hackney) /home/book/my_web/deps/hackney/src/hackney.erl:362: :hackney.send_request/2
    (httpoison) lib/httpoison/base.ex:439: HTTPoison.Base.request/9
    (my_web) lib/my_web.ex:37: MyWeb.page_request/2
Last message: :work
State: nil

I thought this code should catch any error

but in iex works:

Interactive Elixir (1.6.0) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> try do
...(1)> raise ArgumentError
...(1)> rescue
...(1)> error -> {:error, error}
...(1)> end
{:error, %ArgumentError{message: "argument error"}}

I looked through the documentation, but could not find the answer

elixir 1.6.1

example url http://google.com

  defp default_params(timeout \\ 25) do
      [ssl: [verify: :verify_none],
      timeout: timeout*1000,
      recv_timeout: timeout*1000,
      connect_timeout: timeout*1000,
      follow_redirect: true,
      hackney: [pool: false, insecure: true]]
  end

Upvotes: 0

Views: 466

Answers (2)

bschaeffer
bschaeffer

Reputation: 2904

I don't think that ArgumentError is being raised in your block, but by :hackney in MyWeb.WebWorker1 which is probably a separate process. You cannot rescue exceptions from a separate process.

Is HTTPoison async? I bet it still returns an error. If you added a Logger line to the :error case, I believe you'd see an error message there:

{:error, reason} ->
  Logger.debug(inspect(reason))
  {:error, reason}

Upvotes: 0

PatNowak
PatNowak

Reputation: 5812

To use try rescue here you should use HTTPoison.request!, which raises an error, not HTTPoison.request, which returns {:ok, result} or {:error, error}.

The clause rescue will not be triggered when {:error, error} tuple is returned, only when some Error is raised.

Upvotes: 0

Related Questions