diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f4137b22..17e36a2360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp ### Fixes +- [#5003](https://github.com/blockscout/blockscout/pull/5003) - API router refactoring - [#4979](https://github.com/blockscout/blockscout/pull/4979), [#4993](https://github.com/blockscout/blockscout/pull/4993) - Store total gas_used in addresses table - [#4977](https://github.com/blockscout/blockscout/pull/4977) - Export token transfers on address: include transfers on contract itself - [#4976](https://github.com/blockscout/blockscout/pull/4976) - Handle :econnrefused in pending transactions fetcher diff --git a/apps/block_scout_web/lib/block_scout_web/api_router.ex b/apps/block_scout_web/lib/block_scout_web/api_router.ex index ddd34e8035..8fb9698488 100644 --- a/apps/block_scout_web/lib/block_scout_web/api_router.ex +++ b/apps/block_scout_web/lib/block_scout_web/api_router.ex @@ -18,37 +18,45 @@ defmodule BlockScoutWeb.ApiRouter do plug(:accepts, ["json"]) end - scope "/v1", BlockScoutWeb.API.V1, as: :api_v1 do + scope "/v1", as: :api_v1 do pipe_through(:api) + alias BlockScoutWeb.API.{RPC, V1} + alias BlockScoutWeb.API.V1.HealthController + get("/health", HealthController, :health) - if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do - post("/decompiled_smart_contract", DecompiledSmartContractController, :create) - post("/verified_smart_contracts", VerifiedSmartContractController, :create) + if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do + get("/supply", V1.SupplyController, :supply) + post("/eth-rpc", RPC.EthController, :eth_request) end - end - - if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do - scope "/" do - alias BlockScoutWeb.API.{RPC, V1} - pipe_through(:api) - scope "/v1", as: :api_v1 do - get("/supply", V1.SupplyController, :supply) - post("/eth-rpc", RPC.EthController, :eth_request) - end + if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do + post("/decompiled_smart_contract", V1.DecompiledSmartContractController, :create) + post("/verified_smart_contracts", V1.VerifiedSmartContractController, :create) + end - # For backward compatibility. Should be removed - post("/eth-rpc", RPC.EthController, :eth_request) + if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do + forward("/", RPC.RPCTranslator, %{ + "block" => {RPC.BlockController, []}, + "account" => {RPC.AddressController, []}, + "logs" => {RPC.LogsController, []}, + "token" => {RPC.TokenController, []}, + "stats" => {RPC.StatsController, []}, + "contract" => {RPC.ContractController, [:verify]}, + "transaction" => {RPC.TransactionController, []} + }) end end + # For backward compatibility. Should be removed scope "/" do pipe_through(:api) alias BlockScoutWeb.API.RPC - scope "/v1", as: :api_v1 do - forward("/", RPC.RPCTranslator, %{ + if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do + post("/eth-rpc", RPC.EthController, :eth_request) + + forward("/", RPCTranslatorForwarder, %{ "block" => {RPC.BlockController, []}, "account" => {RPC.AddressController, []}, "logs" => {RPC.LogsController, []}, @@ -58,16 +66,5 @@ defmodule BlockScoutWeb.ApiRouter do "transaction" => {RPC.TransactionController, []} }) end - - # For backward compatibility. Should be removed - forward("/", RPCTranslatorForwarder, %{ - "block" => {RPC.BlockController, []}, - "account" => {RPC.AddressController, []}, - "logs" => {RPC.LogsController, []}, - "token" => {RPC.TokenController, []}, - "stats" => {RPC.StatsController, []}, - "contract" => {RPC.ContractController, [:verify]}, - "transaction" => {RPC.TransactionController, []} - }) end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex index 9f9de75e8a..a47b429172 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex @@ -26,7 +26,8 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do def init(opts), do: opts def call(%Conn{params: %{"module" => module, "action" => action}} = conn, translations) do - with {:ok, {controller, write_actions}} <- translate_module(translations, module), + with true <- valid_api_request_path(conn), + {:ok, {controller, write_actions}} <- translate_module(translations, module), {:ok, action} <- translate_action(action), true <- action_accessed?(action, write_actions), {:ok, conn} <- call_controller(conn, controller, action) do @@ -108,4 +109,12 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do e -> {:error, Exception.format(:error, e, __STACKTRACE__)} end + + defp valid_api_request_path(conn) do + if conn.request_path == "/api" || conn.request_path == "/api/v1" do + true + else + false + end + end end diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/rpc_translator_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/rpc_translator_test.exs index bcb12d5af6..a5b23b2532 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/rpc_translator_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/rpc_translator_test.exs @@ -23,7 +23,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do describe "call" do test "with a bad module", %{conn: conn} do - conn = %Conn{conn | params: %{"module" => "test", "action" => "test"}} + conn = %Conn{conn | params: %{"module" => "test", "action" => "test"}, request_path: "/api"} result = RPCTranslator.call(conn, %{}) assert result.halted @@ -35,7 +35,11 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do end test "with a bad action atom", %{conn: conn} do - conn = %Conn{conn | params: %{"module" => "test", "action" => "some_atom_that_should_not_exist"}} + conn = %Conn{ + conn + | params: %{"module" => "test", "action" => "some_atom_that_should_not_exist"}, + request_path: "/api" + } result = RPCTranslator.call(conn, %{"test" => {TestController, []}}) assert result.halted @@ -47,7 +51,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do end test "with an invalid controller action", %{conn: conn} do - conn = %Conn{conn | params: %{"module" => "test", "action" => "index"}} + conn = %Conn{conn | params: %{"module" => "test", "action" => "index"}, request_path: "/api"} result = RPCTranslator.call(conn, %{"test" => {TestController, []}}) assert result.halted @@ -69,7 +73,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do end test "with a valid request", %{conn: conn} do - conn = %Conn{conn | params: %{"module" => "test", "action" => "test_action"}} + conn = %Conn{conn | params: %{"module" => "test", "action" => "test_action"}, request_path: "/api"} result = RPCTranslator.call(conn, %{"test" => {TestController, []}}) assert json_response(result, 200) == %{}