Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching HTTPoison.Response

Tags:

elixir

I'm trying handle the response from an API call using HTTPoison

In my app context I have

def add_to_cart(data, user) do
  case HTTPoison.post!(
      "https://api.moltin.com/v2/carts/" <> user <> 
      "/items", data,
      [{"Authorization",
        "Bearer #{Agent.get(:token, fn state -> state end)}"},
       {"Content-Type", "application/json"}] do

    {:ok, %HTTPoison.Response{status_code: 201, body: body}} ->
      case Poison.decode(body) do
        {:ok, decoded} -> decoded
        {:error, error} -> {:error, error}
      end

    {:ok, %HTTPoison.Response{status_code: 404}} ->
      IO.puts "Not found :("

    {:error, %HTTPoison.Error{reason: reason}} ->
      IO.inspect reason

  end
end

The error I return is:

CaseClauseError at POST /order
no case clause matching: %HTTPoison.Response{response content}

I have used this pattern elsewhere in my code and it matches fine but when I place it here, it doesn't seem to work.

I'm sure this isn't enough information with which to work but I'm not sure at this point what else to put. Any guidance would be appreciated.

like image 625
Joe McBroom Avatar asked Dec 11 '22 09:12

Joe McBroom


2 Answers

The Elixir convention is: banged versions of functions—instead of {:ok, result} and {:error, reason}—return result on success and raise on error. Grep this page for “Elixir doesn’t impose exceptions” for the reference.

HTTPoison follows this convention.

To make your code work, one should either use HTTPoison.post (not banged) in the very top case, or match the result respectively:

try
  %HTTPoison.Response{status: status, body: body} =
    HTTPoison.post!(...)
  case status do
    201 -> ...
    404 -> ...
  end
rescue
  e in HTTPoison.Error ->
    IO.inspect e
end  
like image 59
Aleksei Matiushkin Avatar answered Dec 30 '22 06:12

Aleksei Matiushkin


What about a nice and classy pattern matching suggested by HTTPoison docs? Just get rid of exclamation mark and try something like this:

case HTTPoison.post(stuff) do
  {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
    decoded_stuff = Poison.decode(body) # use another nice case statement here
  {:ok, %HTTPoison.Response{status_code: 404}} ->
    IO.puts "Not found :("
  {:error, %HTTPoison.Error{reason: reason}} ->
    IO.inspect reason
end
like image 26
Kociamber Avatar answered Dec 30 '22 08:12

Kociamber