defmodule PhilomenaQuery.Search.Client do @moduledoc """ HTTP-level interaction with OpenSearch JSON API. Allows two styles of parameters for bodies: - map: the map is directly encoded as a JSON object - list: each element of the list is encoded as a JSON object and interspersed with newlines. This is used by bulk APIs. """ @receive_timeout 30_000 @type list_or_map :: list() | map() @type result :: {:ok, Req.Response.t()} | {:error, Exception.t()} @doc """ HTTP GET """ @spec get(String.t(), list_or_map()) :: result() def get(url, body) do Req.get(url, encode_options(body)) end @doc """ HTTP POST """ @spec post(String.t(), list_or_map()) :: result() def post(url, body) do Req.post(url, encode_options(body)) end @doc """ HTTP PUT """ @spec put(String.t(), list_or_map()) :: result() def put(url, body) do Req.put(url, encode_options(body)) end @doc """ HTTP DELETE """ @spec delete(String.t()) :: result() def delete(url) do Req.delete(url, encode_options()) end defp encode_body(body) when is_map(body), do: Jason.encode!(body) defp encode_body(body) when is_list(body), do: [Enum.map_intersperse(body, "\n", &Jason.encode!(&1)), "\n"] defp encode_options, do: [headers: request_headers(), receive_timeout: @receive_timeout] defp encode_options(body), do: Keyword.merge(encode_options(), body: encode_body(body)) defp request_headers, do: [content_type: "application/json"] end