Last active
January 25, 2024 09:09
-
-
Save PJUllrich/f6ff06d261557433607578ab3207cc10 to your computer and use it in GitHub Desktop.
HTTP Wrapper with optional Caching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Http do | |
@moduledoc """ | |
Exposes functions to make HTTP requests and optionally cache the response. | |
If you want to cache the request, simply add `cache: true` to the | |
request options. You can also define an option time-to-live (TTL) with | |
`cache_ttl: ttl_in_milliseconds`. The default TTL is 5min. | |
Only caches 2xx responses. | |
""" | |
require Logger | |
@default_cache_ttl :timer.minutes(5) | |
def get(url, opts \\ [], http_opts \\ []) do | |
request = fn -> adapter().get(url, opts) end | |
do_request(request, url, http_opts) | |
end | |
def get!(url, opts \\ [], http_opts \\ []) do | |
request = fn -> adapter().get!(url, opts) end | |
do_request(request, url, http_opts) | |
end | |
def post(url, opts \\ [], http_opts \\ []) do | |
request = fn -> adapter().post(url, opts) end | |
do_request(request, url, http_opts) | |
end | |
def delete(url, opts \\ [], http_opts \\ []) do | |
request = fn -> adapter().delete(url, opts) end | |
do_request(request, url, http_opts) | |
end | |
# Private functions | |
defp do_request(request, url, opts) do | |
request | |
|> maybe_read_cache(url, opts) | |
|> maybe_write_cache(url, opts) | |
end | |
defp maybe_read_cache(request, url, opts) do | |
with true <- Keyword.get(opts, :cache), | |
{:ok, results} <- read_cache(url) do | |
Logger.debug("Cache hit for #{url}") | |
results | |
else | |
_ -> | |
Logger.debug("Requesting from #{url}") | |
request.() | |
end | |
end | |
defp maybe_write_cache({:ok, results}, url, opts) do | |
results = maybe_write_cache(results, url, opts) | |
{:ok, results} | |
end | |
defp maybe_write_cache(%{status: status} = results, url, opts) when status in 200..299 do | |
if Keyword.get(opts, :cache), do: write_cache(url, results, opts) | |
results | |
end | |
defp maybe_write_cache(result, _url, _opts), do: result | |
defp read_cache(url) do | |
case Cachex.get(:http, url) do | |
{:ok, nil} -> {:error, :not_found} | |
{:ok, results} -> {:ok, results} | |
{:error, _} -> {:error, :not_found} | |
end | |
end | |
defp write_cache(url, results, opts) do | |
ttl = Keyword.get(opts, :cache_ttl, @default_cache_ttl) | |
{:ok, true} = Cachex.put(:http, url, results, ttl: ttl) | |
end | |
defp adapter(), do: Application.get_env(:my_app, :http_adapter) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment