Add possibility to add extra headers with RPC URL

pull/7898/head
Maxim Filonov 1 year ago
parent 8c07aece2f
commit 347f5d3641
  1. 1
      CHANGELOG.md
  2. 10
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
  3. 6
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http/httpoison.ex
  4. 20
      apps/ethereum_jsonrpc/test/ethereum_jsonrpc/http/mox_test.exs
  5. 9
      config/config_helper.exs
  6. 6
      config/runtime.exs
  7. 1
      docker-compose/envs/common-blockscout.env
  8. 3
      docker/Makefile

@ -4,6 +4,7 @@
### Features ### Features
- [#7898](https://github.com/blockscout/blockscout/pull/7898) - Add possibility to add extra headers with JSON RPC URL
- [#7836](https://github.com/blockscout/blockscout/pull/7836) - Improve unverified email flow - [#7836](https://github.com/blockscout/blockscout/pull/7836) - Improve unverified email flow
- [#7784](https://github.com/blockscout/blockscout/pull/7784) - Search improvements: Add new fields, light refactoring - [#7784](https://github.com/blockscout/blockscout/pull/7784) - Search improvements: Add new fields, light refactoring
- [#7811](https://github.com/blockscout/blockscout/pull/7811) - Filter addresses before insertion - [#7811](https://github.com/blockscout/blockscout/pull/7811) - Filter addresses before insertion

@ -14,7 +14,7 @@ defmodule EthereumJSONRPC.HTTP do
@doc """ @doc """
Sends JSONRPC request encoded as `t:iodata/0` to `url` with `options` Sends JSONRPC request encoded as `t:iodata/0` to `url` with `options`
""" """
@callback json_rpc(url :: String.t(), json :: iodata(), options :: term()) :: @callback json_rpc(url :: String.t(), json :: iodata(), headers :: [{String.t(), String.t()}], options :: term()) ::
{:ok, %{body: body :: String.t(), status_code: status_code :: pos_integer()}} {:ok, %{body: body :: String.t(), status_code: status_code :: pos_integer()}}
| {:error, reason :: term} | {:error, reason :: term}
@ -26,7 +26,7 @@ defmodule EthereumJSONRPC.HTTP do
url = url(options, method) url = url(options, method)
http_options = Keyword.fetch!(options, :http_options) http_options = Keyword.fetch!(options, :http_options)
with {:ok, %{body: body, status_code: code}} <- http.json_rpc(url, json, http_options), with {:ok, %{body: body, status_code: code}} <- http.json_rpc(url, json, headers(), http_options),
{:ok, json} <- decode_json(request: [url: url, body: json], response: [status_code: code, body: body]), {:ok, json} <- decode_json(request: [url: url, body: json], response: [status_code: code, body: body]),
{:ok, response} <- handle_response(json, code) do {:ok, response} <- handle_response(json, code) do
{:ok, response} {:ok, response}
@ -66,7 +66,7 @@ defmodule EthereumJSONRPC.HTTP do
json = encode_json(batch) json = encode_json(batch)
case http.json_rpc(url, json, http_options) do case http.json_rpc(url, json, headers(), http_options) do
{:ok, %{status_code: status_code} = response} when status_code in [413, 504] -> {:ok, %{status_code: status_code} = response} when status_code in [413, 504] ->
rechunk_json_rpc(chunks, options, response, decoded_response_bodies) rechunk_json_rpc(chunks, options, response, decoded_response_bodies)
@ -203,4 +203,8 @@ defmodule EthereumJSONRPC.HTTP do
ArgumentError -> ArgumentError ->
:error :error
end end
defp headers do
Application.get_env(:ethereum_jsonrpc, __MODULE__)[:headers]
end
end end

@ -8,8 +8,8 @@ defmodule EthereumJSONRPC.HTTP.HTTPoison do
@behaviour HTTP @behaviour HTTP
@impl HTTP @impl HTTP
def json_rpc(url, json, options) when is_binary(url) and is_list(options) do def json_rpc(url, json, headers, options) when is_binary(url) and is_list(options) do
case HTTPoison.post(url, json, [{"Content-Type", "application/json"}], options) do case HTTPoison.post(url, json, headers, options) do
{:ok, %HTTPoison.Response{body: body, status_code: status_code}} -> {:ok, %HTTPoison.Response{body: body, status_code: status_code}} ->
{:ok, %{body: body, status_code: status_code}} {:ok, %{body: body, status_code: status_code}}
@ -18,5 +18,5 @@ defmodule EthereumJSONRPC.HTTP.HTTPoison do
end end
end end
def json_rpc(url, _json, _options) when is_nil(url), do: {:error, "URL is nil"} def json_rpc(url, _json, _headers, _options) when is_nil(url), do: {:error, "URL is nil"}
end end

@ -38,12 +38,12 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
} do } do
if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do
EthereumJSONRPC.HTTP.Mox EthereumJSONRPC.HTTP.Mox
|> expect(:json_rpc, 2, fn _url, json, _options -> |> expect(:json_rpc, 2, fn _url, json, _headers, _options ->
assert IO.iodata_to_binary(json) =~ ":13000" assert IO.iodata_to_binary(json) =~ ":13000"
{:ok, %{body: "413 Request Entity Too Large", status_code: 413}} {:ok, %{body: "413 Request Entity Too Large", status_code: 413}}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ ":13000" refute json_binary =~ ":13000"
@ -58,7 +58,7 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
{:ok, %{body: body, status_code: 200}} {:ok, %{body: body, status_code: 200}}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ ":6499" refute json_binary =~ ":6499"
@ -107,10 +107,10 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do
EthereumJSONRPC.HTTP.Mox EthereumJSONRPC.HTTP.Mox
|> expect(:json_rpc, fn _url, _json, _options -> |> expect(:json_rpc, fn _url, _json, _headers, _options ->
{:ok, %{body: "504 Gateway Timeout", status_code: 504}} {:ok, %{body: "504 Gateway Timeout", status_code: 504}}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ "0xD2849" refute json_binary =~ "0xD2849"
@ -141,7 +141,7 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
{:ok, %{body: body, status_code: 200}} {:ok, %{body: body, status_code: 200}}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ "0xD2844" refute json_binary =~ "0xD2844"
@ -199,10 +199,10 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do if json_rpc_named_arguments[:transport_options][:http] == EthereumJSONRPC.HTTP.Mox do
EthereumJSONRPC.HTTP.Mox EthereumJSONRPC.HTTP.Mox
|> expect(:json_rpc, fn _url, _json, _options -> |> expect(:json_rpc, fn _url, _json, _headers, _options ->
{:error, :timeout} {:error, :timeout}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ "0xD2849" refute json_binary =~ "0xD2849"
@ -233,7 +233,7 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
{:ok, %{body: body, status_code: 200}} {:ok, %{body: body, status_code: 200}}
end) end)
|> expect(:json_rpc, fn _url, json, _options -> |> expect(:json_rpc, fn _url, json, _headers, _options ->
json_binary = IO.iodata_to_binary(json) json_binary = IO.iodata_to_binary(json)
refute json_binary =~ "0xD2844" refute json_binary =~ "0xD2844"
@ -293,7 +293,7 @@ defmodule EthereumJSONRPC.HTTP.MoxTest do
json = Jason.encode_to_iodata!(payload) json = Jason.encode_to_iodata!(payload)
http_options = Keyword.fetch!(transport_options, :http_options) http_options = Keyword.fetch!(transport_options, :http_options)
assert {:ok, %{body: body, status_code: 413}} = http.json_rpc(url, json, http_options) assert {:ok, %{body: body, status_code: 413}} = http.json_rpc(url, json, [], http_options)
assert body =~ "413 Request Entity Too Large" assert body =~ "413 Request Entity Too Large"
end end

@ -119,4 +119,13 @@ defmodule ConfigHelper do
transformer transformer
end end
end end
@spec parse_json_env_var(String.t(), String.t()) :: any()
def parse_json_env_var(env_var, default_value) do
env_var
|> safe_get_env(default_value)
|> Jason.decode!()
rescue
err -> raise "Invalid JSON in environment variable #{env_var}: #{inspect(err)}"
end
end end

@ -150,6 +150,12 @@ config :ethereum_jsonrpc,
ipc_path: System.get_env("IPC_PATH"), ipc_path: System.get_env("IPC_PATH"),
disable_archive_balances?: ConfigHelper.parse_bool_env_var("ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES") disable_archive_balances?: ConfigHelper.parse_bool_env_var("ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES")
config :ethereum_jsonrpc, EthereumJSONRPC.HTTP,
headers:
%{"Content-Type" => "application/json"}
|> Map.merge(ConfigHelper.parse_json_env_var("ETHEREUM_JSONRPC_HTTP_HEADERS", "{}"))
|> Map.to_list()
config :ethereum_jsonrpc, EthereumJSONRPC.Geth, config :ethereum_jsonrpc, EthereumJSONRPC.Geth,
debug_trace_transaction_timeout: System.get_env("ETHEREUM_JSONRPC_DEBUG_TRACE_TRANSACTION_TIMEOUT", "5s"), debug_trace_transaction_timeout: System.get_env("ETHEREUM_JSONRPC_DEBUG_TRACE_TRANSACTION_TIMEOUT", "5s"),
tracer: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "call_tracer") tracer: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "call_tracer")

@ -12,6 +12,7 @@ LOGO=/images/blockscout_logo.svg
# ETHEREUM_JSONRPC_WS_URL= # ETHEREUM_JSONRPC_WS_URL=
ETHEREUM_JSONRPC_TRANSPORT=http ETHEREUM_JSONRPC_TRANSPORT=http
ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=false ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=false
# ETHEREUM_JSONRPC_HTTP_HEADERS=
IPC_PATH= IPC_PATH=
NETWORK_PATH=/ NETWORK_PATH=/
BLOCKSCOUT_HOST= BLOCKSCOUT_HOST=

@ -60,6 +60,9 @@ endif
ifdef ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES ifdef ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES
BLOCKSCOUT_CONTAINER_PARAMS += -e 'ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=$(ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES)' BLOCKSCOUT_CONTAINER_PARAMS += -e 'ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=$(ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES)'
endif endif
ifdef ETHEREUM_JSONRPC_HTTP_HEADERS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'ETHEREUM_JSONRPC_HTTP_HEADERS=$(ETHEREUM_JSONRPC_HTTP_HEADERS)'
endif
ifdef IPC_PATH ifdef IPC_PATH
BLOCKSCOUT_CONTAINER_PARAMS += -e 'IPC_PATH=$(IPC_PATH)' BLOCKSCOUT_CONTAINER_PARAMS += -e 'IPC_PATH=$(IPC_PATH)'
endif endif

Loading…
Cancel
Save