Migrate HTTPoison to Finch (#2054)

Signed-off-by: Manu S Ajith <neo@codingarena.in>

Signed-off-by: Manu S Ajith <neo@codingarena.in>
This commit is contained in:
Manu S Ajith 2022-08-15 02:41:48 -05:00 committed by GitHub
parent 5c83ea77de
commit 777c69b1d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 51 deletions

View File

@ -44,7 +44,27 @@ defmodule Plausible.Application do
config = Application.fetch_env!(:plausible, Plausible.Finch)
pool_config = %{
:default => [size: config[:default_pool_size], count: config[:default_pool_count]]
:default => [size: config[:default_pool_size], count: config[:default_pool_count]],
"https://vendors.paddle.com" => [
protocol: :http2,
count: 50,
conn_opts: [transport_opts: [timeout: 15_000]]
],
"https://www.googleapis.com" => [
protocol: :http2,
count: 200,
conn_opts: [transport_opts: [timeout: 15_000]]
],
"https://analyticsreporting.googleapis.com" => [
protocol: :http2,
count: 200,
conn_opts: [transport_opts: [timeout: 15_000]]
],
"https://icons.duckduckgo.com" => [
protocol: :http2,
count: 100,
conn_opts: [transport_opts: [timeout: 15_000]]
]
}
sentry_dsn = Application.get_env(:sentry, :dsn)

View File

@ -1,4 +1,6 @@
defmodule Plausible.Billing.PaddleApi do
alias Plausible.HTTPClient
@update_endpoint "https://vendors.paddle.com/api/2.0/subscription/users/update"
@get_endpoint "https://vendors.paddle.com/api/2.0/subscription/users"
@headers [
@ -21,10 +23,10 @@ defmodule Plausible.Billing.PaddleApi do
}
{:ok, response} =
HTTPoison.post(
HTTPClient.post(
vendors_domain() <> "/api/2.0/subscription/preview_update",
Jason.encode!(params),
@headers
@headers,
Jason.encode!(params)
)
body = Jason.decode!(response.body)
@ -50,7 +52,7 @@ defmodule Plausible.Billing.PaddleApi do
quantity: 1
})
{:ok, response} = HTTPoison.post(@update_endpoint, Jason.encode!(params), @headers)
{:ok, response} = HTTPClient.post(@update_endpoint, @headers, Jason.encode!(params))
body = Jason.decode!(response.body)
if body["success"] do
@ -69,7 +71,7 @@ defmodule Plausible.Billing.PaddleApi do
subscription_id: paddle_subscription_id
}
{:ok, response} = HTTPoison.post(@get_endpoint, Jason.encode!(params), @headers)
{:ok, response} = HTTPClient.post(@get_endpoint, @headers, Jason.encode!(params))
body = Jason.decode!(response.body)
if body["success"] do
@ -94,7 +96,7 @@ defmodule Plausible.Billing.PaddleApi do
to: Timex.shift(Timex.today(), days: 1) |> Timex.format!("{YYYY}-{0M}-{0D}")
}
case HTTPoison.post(invoices_endpoint(), Jason.encode!(params), @headers) do
case HTTPClient.post(invoices_endpoint(), @headers, Jason.encode!(params)) do
{:ok, response} ->
body = Jason.decode!(response.body)

View File

@ -1,4 +1,6 @@
defmodule Plausible.Google.HTTP do
alias Plausible.HTTPClient
@spec get_report(module(), Plausible.Google.ReportRequest.t()) ::
{:ok, {[map()], String.t() | nil}} | {:error, any()}
def get_report(http_client, %Plausible.Google.ReportRequest{} = report_request) do
@ -58,31 +60,46 @@ defmodule Plausible.Google.HTTP do
end
def list_sites(access_token) do
"https://www.googleapis.com/webmasters/v3/sites"
|> HTTPoison.get!("Content-Type": "application/json", Authorization: "Bearer #{access_token}")
url = "https://www.googleapis.com/webmasters/v3/sites"
headers = [{"Content-Type", "application/json"}, {"Authorization", "Bearer #{access_token}"}]
{:ok, response} = HTTPClient.get(url, headers)
response
|> Map.get(:body)
|> Jason.decode!()
|> then(&{:ok, &1})
end
def fetch_access_token(code) do
"https://www.googleapis.com/oauth2/v4/token"
|> HTTPoison.post!(
"client_id=#{client_id()}&client_secret=#{client_secret()}&code=#{code}&grant_type=authorization_code&redirect_uri=#{redirect_uri()}",
"Content-Type": "application/x-www-form-urlencoded"
)
url = "https://www.googleapis.com/oauth2/v4/token"
headers = [{"Content-Type", "application/x-www-form-urlencoded"}]
params =
"client_id=#{client_id()}&client_secret=#{client_secret()}&code=#{code}&grant_type=authorization_code&redirect_uri=#{redirect_uri()}"
{:ok, response} = HTTPClient.post(url, headers, params)
response
|> Map.get(:body)
|> Jason.decode!()
end
def list_views_for_user(access_token) do
"https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles"
|> HTTPoison.get!(Authorization: "Bearer #{access_token}")
|> case do
%{body: body, status_code: 200} ->
url =
"https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles"
headers = [{"Authorization", "Bearer #{access_token}"}]
case HTTPClient.get(url, headers) do
{:ok, %Finch.Response{body: body, status: 200}} ->
{:ok, Jason.decode!(body)}
%{body: body} ->
{:error, %Mint.TransportError{reason: reason}} ->
Sentry.capture_message("Error fetching Google view ID", extra: inspect(reason))
{:error, reason}
{:error, %Finch.Response{body: body}} ->
Sentry.capture_message("Error fetching Google view ID", extra: Jason.decode!(body))
{:error, body}
end
@ -108,27 +125,23 @@ defmodule Plausible.Google.HTTP do
dimensionFilterGroups: filter_groups
})
:post
|> Finch.build(
"https://www.googleapis.com/webmasters/v3/sites/#{property}/searchAnalytics/query",
[{"Authorization", "Bearer #{access_token}"}],
params
)
|> Finch.request(Plausible.Finch)
|> case do
{:ok, %{status: 200, body: body}} ->
url = "https://www.googleapis.com/webmasters/v3/sites/#{property}/searchAnalytics/query"
headers = [{"Authorization", "Bearer #{access_token}"}]
case HTTPClient.post(url, headers, params) do
{:ok, %Finch.Response{body: body, status: 200}} ->
{:ok, Jason.decode!(body)}
{:ok, %{status: 401, body: body}} ->
{:ok, %Finch.Response{body: body, status: 401}} ->
Sentry.capture_message("Error fetching Google queries", extra: Jason.decode!(body))
{:error, :invalid_credentials}
{:ok, %{status: 403, body: body}} ->
{:ok, %Finch.Response{body: body, status: 403}} ->
body = Jason.decode!(body)
Sentry.capture_message("Error fetching Google queries", extra: body)
{:error, get_in(body, ["error", "message"])}
{:ok, %{body: body}} ->
{:ok, %Finch.Response{body: body}} ->
Sentry.capture_message("Error fetching Google queries", extra: Jason.decode!(body))
{:error, :unknown}
end
@ -138,16 +151,17 @@ defmodule Plausible.Google.HTTP do
defp property_base_url(url), do: url
def refresh_auth_token(refresh_token) do
"https://www.googleapis.com/oauth2/v4/token"
|> HTTPoison.post!(
"client_id=#{client_id()}&client_secret=#{client_secret()}&refresh_token=#{refresh_token}&grant_type=refresh_token&redirect_uri=#{redirect_uri()}",
"Content-Type": "application/x-www-form-urlencoded"
)
|> case do
%{body: body, status_code: 200} ->
url = "https://www.googleapis.com/oauth2/v4/token"
headers = [{"Content-Type", "application/x-www-form-urlencoded"}]
params =
"client_id=#{client_id()}&client_secret=#{client_secret()}&refresh_token=#{refresh_token}&grant_type=refresh_token&redirect_uri=#{redirect_uri()}"
case HTTPClient.post(url, headers, params) do
{:ok, %Finch.Response{body: body, status: 200}} ->
{:ok, Jason.decode!(body)}
%{body: body} ->
{:error, %Finch.Response{body: body}} ->
body
|> Jason.decode!(body)
|> Map.get("error")
@ -175,15 +189,11 @@ defmodule Plausible.Google.HTTP do
]
})
"https://analyticsreporting.googleapis.com/v4/reports:batchGet"
|> HTTPoison.post!(
params,
[Authorization: "Bearer #{access_token}"],
timeout: 15_000,
recv_timeout: 15_000
)
|> case do
%{status_code: 200, body: body} ->
url = "https://analyticsreporting.googleapis.com/v4/reports:batchGet"
headers = [{"Authorization", "Bearer #{access_token}"}]
case HTTPClient.post(url, headers, params) do
{:ok, %Finch.Response{body: body, status: 200}} ->
report = List.first(Jason.decode!(body)["reports"])
date =
@ -197,7 +207,7 @@ defmodule Plausible.Google.HTTP do
{:ok, date}
%{body: body} ->
{:error, %Finch.Response{body: body}} ->
Sentry.capture_message("Error fetching Google view ID", extra: Jason.decode!(body))
{:error, body}
end

View File

@ -0,0 +1,33 @@
defmodule Plausible.HTTPClient do
@moduledoc """
HTTP Client built on top of Finch.
"""
@doc """
Make a POST request
"""
def post(url, headers \\ [], params \\ nil) do
call(:post, url, headers, params)
end
@doc """
Make a GET request
"""
def get(url, headers \\ [], params \\ nil) do
call(:get, url, headers, params)
end
defp call(method, url, headers, params) do
method
|> build_request(url, headers, params)
|> do_request
end
defp build_request(method, url, headers, params) do
Finch.build(method, url, headers, params)
end
defp do_request(request) do
Finch.request(request, Plausible.Finch)
end
end

View File

@ -1,4 +1,6 @@
defmodule PlausibleWeb.Captcha do
alias Plausible.HTTPClient
@verify_endpoint "https://hcaptcha.com/siteverify"
def enabled? do
@ -13,7 +15,11 @@ defmodule PlausibleWeb.Captcha do
def verify(token) do
if enabled?() do
res =
HTTPoison.post!(@verify_endpoint, {:form, [{"response", token}, {"secret", secret()}]})
HTTPClient.post(
@verify_endpoint,
[],
{:form, [{"response", token}, {"secret", secret()}]}
)
json = Jason.decode!(res.body)
json["success"]

View File

@ -1,5 +1,6 @@
defmodule PlausibleWeb.Favicon do
import Plug.Conn
alias Plausible.HTTPClient
def init(_) do
domains =
@ -19,7 +20,7 @@ defmodule PlausibleWeb.Favicon do
["favicon", "sources", source] ->
clean_source = URI.decode_www_form(source)
domain = Map.get(favicon_domains, clean_source, clean_source)
res = HTTPoison.get!("https://icons.duckduckgo.com/ip3/#{domain}.ico")
res = HTTPClient.get("https://icons.duckduckgo.com/ip3/#{domain}.ico")
conn =
Enum.filter(res.headers, fn {key, _val} -> key != "Transfer-Encoding" end)