Packages

An API wrapper for the Scrapy Cloud API provided by ScrapingHub.com.

Current section

Files

Jump to
scrapy_cloud_ex lib endpoints.ex
Raw

lib/endpoints.ex

defmodule ScrapyCloudEx.Endpoints do
@moduledoc """
Documents commonalities between all endpoint-related functions.
## Options
The last argument provided to most endpoint functions is a keyword list
of options. These options are made available to the HttpAdapter during the
API request.
- `:decoder` - specifies how the response body should be processed. Can be
a module implementing the `ScrapyCloudEx.Decoder` behaviour, or a function
conforming to the `t:ScrapyCloudEx.Decode.decoder_function/2` typespec.
Defaults to `ScrapyCloudEx.Decoders.Default`.
- `:headers` - list of headers that are added to the `ScrapyCloudEx.HttpAdapter.RequestConfig`
`headers` attribute provided to the HttpAdapter instance making the API call.
The default HttpAdapter does not make use of this option.
- `:http_adapter` - specifies the module to use to make the HTTP request to
the API. This module is expected to implement the `ScrapyCloudEx.HttpAdapter`
behaviour. Defaults to `ScrapyCloudEx.HttpAdapters.Default`.
"""
require Logger
# warns on unscoped params and puts relevant parameters into scope
@doc false
@spec scope_params(Keyword.t(), atom, [atom, ...]) :: Keyword.t()
def scope_params(params, scope_name, expected_scoped_params) do
unscoped = params |> get_params(expected_scoped_params)
scoped = Keyword.get(params, scope_name, [])
warn_on_unscoped_params(scoped, unscoped, scope_name)
scoped_params = unscoped |> Keyword.merge(scoped)
params
|> Enum.reject(fn {k, _} -> Enum.member?(expected_scoped_params, k) end)
|> Keyword.put(scope_name, scoped_params)
end
@doc false
@spec merge_scope(Keyword.t(), atom()) :: Keyword.t()
def merge_scope(params, scope) do
scoped_params = Keyword.get(params, scope, [])
params
|> Keyword.merge(scoped_params)
|> Keyword.delete(scope)
end
@spec get_params(Keyword.t(), [atom]) :: Keyword.t()
defp get_params(params, keys) do
keys
|> Enum.map(&{&1, Keyword.get(params, &1)})
|> Enum.reject(fn {_, v} -> v == nil end)
end
@spec warn_on_unscoped_params(Keyword.t(), Keyword.t(), atom) :: any
defp warn_on_unscoped_params(scoped, unscoped, scope_name) do
if length(unscoped) > 0 do
Logger.warn(
"values `#{inspect(unscoped)}` should be provided within the `#{scope_name}` parameter"
)
common_params = intersection(Keyword.keys(unscoped), Keyword.keys(scoped))
if length(common_params) > 0 do
Logger.warn(
"top-level #{scope_name} params `#{inspect(common_params)}` will be overridden by values provided in `#{
scope_name
}` parameter"
)
end
end
end
@spec intersection(list, list) :: list
defp intersection(a, b) when is_list(a) and is_list(b) do
items_only_in_a = a -- b
a -- items_only_in_a
end
end