Pattern Matching a HTTP request?

I saw someone fetching an api and people told him/her to pattern match the body out, but how does that work?

def fetch(data), do: HTTPoison.get!("test-api.com/#{data}")

info: Its returning a lot of informations like date, and much more but how can I only log the body? like only what the api returns

1 Like

You should match the response…

Maybe something like this…

def fetch(data), do: %{body: body} = HTTPoison.get!("test-api.com/#{data}"); body

but what I usually do is

case HTTPoison.get!("test-api.com/#{data}") do
  %HTTPoison.Response{body: body, status_code: 200} -> ...
  ... -> ...
end
1 Like

what comes after the → … in the case statement?

def fetch(datal) do
    case HTTPoison.get!("test-api.com#{data}") do
       %HTTPoison.Response{body: body} ->
        {:ok, body} ->
          IO.puts(body)
        {:error, error} ->
          IO.puts("Error #{error}")
        end
  end
1 Like

It’s a case expression, not a statement, and after the -> there comes whatever you want to do with the body.

2 Likes

can I somehow return an error in the console when something goes wrong? its erroring at {body: body} with something like wrong syntax

What is the code you use and the exact error message? Just {foo: bar} would indeed be invalid syntax. That’s not map, nor tuple

the code from the very first answer

And the exact error message?

syntax error before: ‘->’

This is wrong syntax…

my whole code, I would like to return the body if everything is fine and an error if something goes wrong
its coming from your response, the very first one

def fetch(data) do
  case HTTPoison.get!("") do 
    %HTTPoison.Response{body: body} ->
      {:ok, body} ->
        IO.puts(body)
      {:error, error} ->
        IO.puts("Error #{error}")
      end
  end

This should be…

def fetch(data) do
  case HTTPoison.get!("") do 
    %HTTPoison.Response{body: body} ->
        IO.puts(body)
  end

And You should check status, as get! will always return a response (or async response), not {:ok, …}, nor {:error, …}

1 Like

after the -> of your case you have to return something before another matching. for example IO.puts(body) as @kokolegorille suggested, or whatever you want to be returned on this specific matching.

2 Likes

how can I return the status correctly? because normally, when everything goes right => return body, else error message

The status_code is part of the response, as the body, headers…

Here is the spec…

t() :: %HTTPoison.Response{
  body: term(),
  headers: list(),
  request: HTTPoison.Request.t(),
  request_url: HTTPoison.Request.url(),
  status_code: integer()
}

So what You can do is…

def fetch(data) do
  case HTTPoison.get!("") do 
    %HTTPoison.Response{body: body, status_code: 200} ->
        body
    %HTTPoison.Response{status_code: status_code} when status_code > 399 ->
       IO.inspect(status_code, label: "STATUS CODE")
       :error
    response -> # do what you want...
  end
end
1 Like

at t() i get misplaced operator ::/2

spec is not code to type…

https://hexdocs.pm/httpoison/HTTPoison.Response.html#t:t/0

The code is the fetch function

yea lol sorry, one question, after the :error you have “response”, what could I do there?

It’s catch all clause… when status_code is not equal to 200, or lower or equal to 399.

You need to treat all status code, or your code will fail.

for example, with status code 100…199, 201…299, 300…399

:error
response → “what should I do here?”