exhal v8.2.0 ExHal

Use HAL APIs with ease.

Given a resource http://example.com/hal whose HAL representation looks like

{ "name": "Hello!",
  "_links": {
     "self"   : { "href": "http://example.com" },
      "profile": [{ "href": "http://example.com/special" },
                  { "href": "http://example.com/normal" }]
  }
}
iex> {:ok, doc, response_header} = ExHal.client
...> |> ExHal.Client.add_headers("User-Agent": "MyClient/1.0")
...> |> ExHal.Client.get("http://example.com/hal")
%ExHal.Document{...}

Now we have an entry point to the API we can follow links to navigate around.

iex> ExHal.follow_link(doc, "profile")
{:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}

iex> ExHal.follow_link(doc, "self")
{:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}

iex> ExHal.follow_links(doc, "profile")
[{:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}, {:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}]

We can specify headers for each request in addition to the headers specified in the client.

iex> ExHal.follow_links(doc, "profile",
                        headers: ["Accept": "application/vnd.custom.json+type"])
[{:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}, {:ok, %ExHal.Document{...}, %ExHal.ResponseHeader{...}}]

If we try to follow a non-existent or compound link with ExHal.follow_link it will return an error tuple.

iex> ExHal.follow_link(doc, "nonexistent")
{:error, %ExHal.Error{reason: "no such link"}}

iex> ExHal.follow_link(doc, "profile", strict: true)
{:error, %ExHal.Error{reason: "multiple choices"}}

If we try to follow a non-existent with ExHal.follow_links it will return a list of error tuples.

iex> ExHal.follow_links(doc, "nonexistent")
[{:error, %ExHal.Error{reason: "no such link"}}]

Collections

Consider a resource http://example.com/hal-collection whose HAL representation looks like

{ "_links": {
     "self"   : { "href": "http://example.com/hal-collection" },
      "item": [{ "href": "http://example.com/beginning" },
               { "href": "http://example.com/middle" }]
      "next": { "href": "http://example.com/hal-collection?p=2" }
  }
}

and a resource http://example.com/hal-collection?p=2 whose HAL representation looks like

{ "_links": {
     "self"   : { "href": "http://example.com/hal-collection?p=2" },
      "item": [{ "href": "http://example.com/end" }]
  }
}

If we get the first HAL collection resource and turn it into a stream we can use all our favorite Stream functions on it.

iex> collection = ExHal.client
...> |> ExHal.Client.add_headers("User-Agent": "MyClient/1.0")
...> |> ExHal.Client.get("http://example.com/hal-collection")
...> |> ExHal.to_stream
#Function<11.52512309/2 in Stream.resource/3>

iex> Stream.map(collection, fn follow_results ->
...>   case follow_results do
...>     {:ok, a_doc, %ResponseHeader{}} -> ExHal.url(a_doc)}
...>     {:error, _}  -> :error
...>   end
...> end )
["http://example.com/beginning", "http://example.com/middle", "http://example.com/end"]

Link to this section Summary

Link to this section Functions

Returns a default client

Link to this function

fetch(a_document, name)

Link to this function

follow_link(a_doc, name)

Link to this function

follow_link(a_doc, name, opts)

Link to this function

follow_links(a_doc, name)

Link to this function

follow_links(a_doc, name, opts)

Link to this function

follow_links(a_doc, name, missing_link_handler, opts)

Link to this function

get_lazy(a_doc, name, default_fun)

Link to this function

get_property_lazy(a_doc, prop_name, default_fun)

Link to this function

patch(a_doc, name, body)

Link to this function

patch(a_doc, name, body, opts)

Link to this function

post(a_doc, name, body)

Link to this function

post(a_doc, name, body, opts)

Link to this function

to_stream(a_doc)

Returns a stream that yields the items in the rfc 6573 collection represented by a_doc.

Link to this function

url(a_doc, default_fn)