Current section
Files
Jump to
Current section
Files
lib/opecadc_datalink/client.ex
defmodule OpencadcDatalink.Client do
@moduledoc """
Client for an IVOA DataLink service.
"""
require Logger
alias OpencadcDatalink.Parser
@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_stream(cookie_credential)
end
@doc """
Obtain a stream to the given URL.
"""
def to_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> OpencadcDatalink.Client.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
with resource_uri = get_resource_uri(caom_publisher_uri),
service_url =
OpencadcRegistry.Client.lookup_service_url(
resource_uri,
"ivo://ivoa.net/std/DataLink#links-1.0",
"vs:ParamHTTP"
) do
Logger.debug("DataLink service URL '#{service_url}'")
service_url
|> 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
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, body: body} = _response) do
Parser.all(
Parser.from_string(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