Current section

Files

Jump to
opencadc_datalink_client lib opencadc_datalink_client.ex
Raw

lib/opencadc_datalink_client.ex

defmodule OpencadcDatalinkClient do
@moduledoc """
Client for an IVOA DataLink service.
"""
@doc """
Obtain a stream to the primary data.
"""
def get_primary_data_stream(caom_publisher_uri, cookie_credential \\ "") do
get_primary_data_url(caom_publisher_uri, cookie_credential)
|> to_bin_stream(cookie_credential)
end
defp to_bin_stream(primary_url, cookie_credential) do
HTTPoison.get!(primary_url, [{"Cookie", "CADC_SSO=\"#{cookie_credential}\""}], [{:stream_to, self()}])
end
@doc """
Obtain the URL containing the '#this' row, meaning the primary data for the given caom_publisher_uri.
## Examples
iex> OpencadcDatalinkClient.get_primary_data_url("ivo://cadc.nrc.ca/IRIS?f008h000/IRAS-100um")
"http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/data/pub/IRIS/I008B4H0.fits"
"""
def get_primary_data_url(caom_publisher_uri, cookie_credential \\ "") do
get_resource_uri(caom_publisher_uri)
|> OpencadcRegistryClient.lookup_service_url("ivo://ivoa.net/std/DataLink#links-1.0", "vs:ParamHTTP")
|> append_search(caom_publisher_uri)
|> HTTPoison.get!([{"Cookie", "CADC_SSO=\"#{cookie_credential}\""}])
|> primary_data_url
|> HTTPoison.get!([{"Cookie", "CADC_SSO=\"#{cookie_credential}\""}])
|> read_redirect
end
defp read_redirect(%HTTPoison.Response{status_code: 303} = response) do
response.headers |> get_header("Location")
end
def primary_data_url(%HTTPoison.Response{status_code: 200} = response) do
Parser.all(Parser.from_string(response.body),
"/VOTABLE/RESOURCE[@type=\"results\"]/TABLE/DATA/TABLEDATA/TR[TD[5][text()=\"#this\"]]/TD[2]")
|> extract_text
end
def primary_data_url(%HTTPoison.Response{status_code: 404}) do
raise ArgumentError, "DataLink target does not exist."
end
defp extract_text(row_items) do
row_items |> Enum.at(0) |> Parser.text
end
def get_resource_uri(caom_publisher_uri) do
URI.parse(caom_publisher_uri)
|> mangle_resource_uri
end
defp mangle_resource_uri(uri) do
"ivo://" <> uri.authority <> uri.path
end
defp append_search(service_url, uri_search) do
URI.parse(service_url)
|> append_search_query(uri_search)
end
defp append_search_query(%URI{query: nil} = service_url, uri_search) do
URI.to_string(service_url) <> "?id=" <> uri_search
end
defp append_search_query(%URI{} = service_url, uri_search) do
URI.to_string(service_url) <> "&id=" <> uri_search
end
defp get_header(headers, key) do
headers
|> Enum.filter(fn({k, _}) -> k == key end)
|> hd
|> elem(1)
end
end