Kevondsmith
Kevondsmith

Reputation: 35

How to get String Pattern Match from body of http get

I'm trying to filter out this response body that I'm getting using Enum.filter and String.match'ing the response body. How would I go about it?

iex(15)>  response = HTTPoison.get!("http://127.0.0.1:8081/service/rest/v1/repositories")       
%HTTPoison.Response{
  body: "[ {\n  \"name\" : \"maven-snapshots\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-snapshots\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-central\",\n  \"format\" : \"maven2\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-central\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://repo1.maven.org/maven2/\"\n    }\n  }\n}, {\n  \"name\" : \"nuget-group\",\n  \"format\" : \"nuget\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-group\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget.org-proxy\",\n  \"format\" : \"nuget\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget.org-proxy\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://www.nuget.org/api/v2/\"\n    }\n  }\n}, {\n  \"name\" : \"maven-releases\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-releases\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget-hosted\",\n  \"format\" : \"nuget\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-hosted\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-public\",\n  \"format\" : \"maven2\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-public\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"Taskmaster1\",\n  \"format\" : \"docker\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/Taskmaster1\",\n  \"attributes\" : { }\n} ]",
  headers: [
    {"Date", "Sun, 27 Oct 2019 20:39:44 GMT"},
    {"Server", "Nexus/3.19.1-01 (OSS)"},
    {"X-Content-Type-Options", "nosniff"},
    {"Content-Type", "application/json"},
    {"Content-Length", "1411"} 
  ],
  request: %HTTPoison.Request{
    body: "",
    headers: [],
    method: :get,
    options: [],
    params: %{},
    url: "http://127.0.0.1:8081/service/rest/v1/repositories"
  },
  request_url: "http://127.0.0.1:8081/service/rest/v1/repositories",
  status_code: 200
}

This is the error I receive:

iex(16)> Enum.filter(response.body, fn {key, _} -> String.match?(key, ~r/\A\n  \"format\" : \"docker\"\z/i) end)
** (Protocol.UndefinedError) protocol Enumerable not implemented for "[ {\n  \"name\" : \"maven-snapshots\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-snapshots\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-central\",\n  \"format\" : \"maven2\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-central\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://repo1.maven.org/maven2/\"\n    }\n  }\n}, {\n  \"name\" : \"nuget-group\",\n  \"format\" : \"nuget\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-group\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget.org-proxy\",\n  \"format\" : \"nuget\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget.org-proxy\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://www.nuget.org/api/v2/\"\n    }\n  }\n}, {\n  \"name\" : \"maven-releases\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-releases\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget-hosted\",\n  \"format\" : \"nuget\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-hosted\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-public\",\n  \"format\" : \"maven2\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-public\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"Taskmaster1\",\n  \"format\" : \"docker\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/Taskmaster1\",\n  \"attributes\" : { }\n} ]" of type BitString. This protocol is implemented for the following type(s): Ecto.Adapters.SQL.Stream, DBConnection.Stream, DBConnection.PrepareStream, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:141: Enumerable.reduce/3
    (elixir) lib/enum.ex:3023: Enum.filter/2

It works with the headers, but not for the body:

iex(16)>  response = HTTPoison.get!("http://127.0.0.1:8081/service/rest/v1/repositories")                       
%HTTPoison.Response{
  body: "[ {\n  \"name\" : \"maven-snapshots\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-snapshots\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-central\",\n  \"format\" : \"maven2\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-central\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://repo1.maven.org/maven2/\"\n    }\n  }\n}, {\n  \"name\" : \"nuget-group\",\n  \"format\" : \"nuget\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-group\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget.org-proxy\",\n  \"format\" : \"nuget\",\n  \"type\" : \"proxy\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget.org-proxy\",\n  \"attributes\" : {\n    \"proxy\" : {\n      \"remoteUrl\" : \"https://www.nuget.org/api/v2/\"\n    }\n  }\n}, {\n  \"name\" : \"maven-releases\",\n  \"format\" : \"maven2\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-releases\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"nuget-hosted\",\n  \"format\" : \"nuget\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/nuget-hosted\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"maven-public\",\n  \"format\" : \"maven2\",\n  \"type\" : \"group\",\n  \"url\" : \"http://127.0.0.1:8081/repository/maven-public\",\n  \"attributes\" : { }\n}, {\n  \"name\" : \"Taskmaster1\",\n  \"format\" : \"docker\",\n  \"type\" : \"hosted\",\n  \"url\" : \"http://127.0.0.1:8081/repository/Taskmaster1\",\n  \"attributes\" : { }\n} ]",
  headers: [
    {"Date", "Sun, 27 Oct 2019 20:47:30 GMT"},
    {"Server", "Nexus/3.19.1-01 (OSS)"},
    {"X-Content-Type-Options", "nosniff"},
    {"Content-Type", "application/json"},
    {"Content-Length", "1411"} 
  ],
  request: %HTTPoison.Request{
    body: "",
    headers: [],
    method: :get,
    options: [],
    params: %{},
    url: "http://127.0.0.1:8081/service/rest/v1/repositories"
  },
  request_url: "http://127.0.0.1:8081/service/rest/v1/repositories",
  status_code: 200
}
iex(17)> Enum.filter(response.headers, fn {key, _} -> String.match?(key, ~r/\Adate\z/i) end)                    
[{"Date", "Sun, 27 Oct 2019 20:47:30 GMT"}]

Upvotes: 0

Views: 700

Answers (2)

Paweł Obrok
Paweł Obrok

Reputation: 23164

The body is a string, so Enum functions don't work with it. It seems to be some kind of JSON, so you probably want to parse it into a datastructure first. You can do that using several elixir libraries, for example using Poison:

response.body
|> Poison.decode!()
|> Enum.filter(fn item ->
  item["format"] == "docker"
end)
|> IO.inspect()

produces:

[
  %{
    "attributes" => %{},
    "format" => "docker",
    "name" => "Taskmaster1",
    "type" => "hosted",
    "url" => "http://127.0.0.1:8081/repository/Taskmaster1"
  }
]

Upvotes: 0

Adam Millerchip
Adam Millerchip

Reputation: 23091

First, a better way to filter the header is like this:

Enum.filter(response.headers, &match?({"Date", _}, &1))

Output:

[{"Date", "Sun, 27 Oct 2019 20:47:30 GMT"}]

For the body, you should decode it from JSON first. You need to pick a JSON library and add it to mix.exs. I'm using Jason. Then you can match in the same way as above:

Jason.decode!(request.body) |> Enum.filter(&match?(%{"name" => "maven-central"}, &1))

Output:

[
  %{
    "attributes" => %{
      "proxy" => %{"remoteUrl" => "https://repo1.maven.org/maven2/"}
    },
    "format" => "maven2",
    "name" => "maven-central",
    "type" => "proxy",
    "url" => "http://127.0.0.1:8081/repository/maven-central"
  }
]

Upvotes: 1

Related Questions