From 7f0dae2f99781f17213b473e1d62aa0f2625f8b0 Mon Sep 17 00:00:00 2001 From: Gary Rennie Date: Wed, 16 Oct 2024 20:09:10 +0100 Subject: [PATCH] fallback to ipv4/ipv6 in the event of an unreachable host error If there is a request failure and the reason implies that the error is due to the usage being ipv4 or ipv6, the alternative is set and the request retries. A variable is used to determine if a retry should be attempted or not. If it is false, this means that a retry is already being attempted, and the request should raise. This is based on: https://github.com/elixir-lang/elixir/blob/9c42348f6407fa315bae00acffe433e9417e2c2e/lib/mix/lib/mix/utils.ex#L687 --- lib/esbuild/npm_registry.ex | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/esbuild/npm_registry.ex b/lib/esbuild/npm_registry.ex index 5a82bd4..56b3e4f 100644 --- a/lib/esbuild/npm_registry.ex +++ b/lib/esbuild/npm_registry.ex @@ -56,11 +56,17 @@ defmodule Esbuild.NpmRegistry do tar end - defp fetch_file!(url) do - case do_fetch(url) do - {:ok, {{_, 200, _}, _headers, body}} -> + defp fetch_file!(url, retry \\ true) do + case {retry, do_fetch(url)} do + {_, {:ok, {{_, 200, _}, _headers, body}}} -> body + {true, {:error, {:failed_connect, [{:to_address, _}, {inet, _, reason}]}}} + when inet in [:inet, :inet6] and + reason in [:ehostunreach, :enetunreach, :eprotonosupport, :nxdomain] -> + :httpc.set_options([ipfamily: fallback(inet)]) + fetch_file!(url, false) + other -> raise """ couldn't fetch #{url}: #{inspect(other)} @@ -71,6 +77,9 @@ defmodule Esbuild.NpmRegistry do end end + defp fallback(:inet), do: :inet6 + defp fallback(:inet6), do: :inet + defp do_fetch(url) do scheme = URI.parse(url).scheme url = String.to_charlist(url)