Merge pull request #5003 from blockscout/vb-api-router-refactoring

API router refactoring
pull/5005/head
Victor Baranov 3 years ago committed by GitHub
commit 108b0c57e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 55
      apps/block_scout_web/lib/block_scout_web/api_router.ex
  3. 11
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex
  4. 12
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/rpc_translator_test.exs

@ -5,6 +5,7 @@
- [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp - [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp
### Fixes ### 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 - [#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 - [#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 - [#4976](https://github.com/blockscout/blockscout/pull/4976) - Handle :econnrefused in pending transactions fetcher

@ -18,37 +18,45 @@ defmodule BlockScoutWeb.ApiRouter do
plug(:accepts, ["json"]) plug(:accepts, ["json"])
end end
scope "/v1", BlockScoutWeb.API.V1, as: :api_v1 do scope "/v1", as: :api_v1 do
pipe_through(:api) pipe_through(:api)
alias BlockScoutWeb.API.{RPC, V1}
alias BlockScoutWeb.API.V1.HealthController
get("/health", HealthController, :health) get("/health", HealthController, :health)
if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do
post("/decompiled_smart_contract", DecompiledSmartContractController, :create) get("/supply", V1.SupplyController, :supply)
post("/verified_smart_contracts", VerifiedSmartContractController, :create) post("/eth-rpc", RPC.EthController, :eth_request)
end 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 if Application.get_env(:block_scout_web, __MODULE__)[:writing_enabled] do
get("/supply", V1.SupplyController, :supply) post("/decompiled_smart_contract", V1.DecompiledSmartContractController, :create)
post("/eth-rpc", RPC.EthController, :eth_request) post("/verified_smart_contracts", V1.VerifiedSmartContractController, :create)
end end
# For backward compatibility. Should be removed if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do
post("/eth-rpc", RPC.EthController, :eth_request) 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
end end
# For backward compatibility. Should be removed
scope "/" do scope "/" do
pipe_through(:api) pipe_through(:api)
alias BlockScoutWeb.API.RPC alias BlockScoutWeb.API.RPC
scope "/v1", as: :api_v1 do if Application.get_env(:block_scout_web, __MODULE__)[:reading_enabled] do
forward("/", RPC.RPCTranslator, %{ post("/eth-rpc", RPC.EthController, :eth_request)
forward("/", RPCTranslatorForwarder, %{
"block" => {RPC.BlockController, []}, "block" => {RPC.BlockController, []},
"account" => {RPC.AddressController, []}, "account" => {RPC.AddressController, []},
"logs" => {RPC.LogsController, []}, "logs" => {RPC.LogsController, []},
@ -58,16 +66,5 @@ defmodule BlockScoutWeb.ApiRouter do
"transaction" => {RPC.TransactionController, []} "transaction" => {RPC.TransactionController, []}
}) })
end 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
end end

@ -26,7 +26,8 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
def init(opts), do: opts def init(opts), do: opts
def call(%Conn{params: %{"module" => module, "action" => action}} = conn, translations) do 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), {:ok, action} <- translate_action(action),
true <- action_accessed?(action, write_actions), true <- action_accessed?(action, write_actions),
{:ok, conn} <- call_controller(conn, controller, action) do {:ok, conn} <- call_controller(conn, controller, action) do
@ -108,4 +109,12 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
e -> e ->
{:error, Exception.format(:error, e, __STACKTRACE__)} {:error, Exception.format(:error, e, __STACKTRACE__)}
end 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 end

@ -23,7 +23,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do
describe "call" do describe "call" do
test "with a bad module", %{conn: conn} 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, %{}) result = RPCTranslator.call(conn, %{})
assert result.halted assert result.halted
@ -35,7 +35,11 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do
end end
test "with a bad action atom", %{conn: conn} do 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, []}}) result = RPCTranslator.call(conn, %{"test" => {TestController, []}})
assert result.halted assert result.halted
@ -47,7 +51,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do
end end
test "with an invalid controller action", %{conn: conn} do 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, []}}) result = RPCTranslator.call(conn, %{"test" => {TestController, []}})
assert result.halted assert result.halted
@ -69,7 +73,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslatorTest do
end end
test "with a valid request", %{conn: conn} do 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, []}}) result = RPCTranslator.call(conn, %{"test" => {TestController, []}})
assert json_response(result, 200) == %{} assert json_response(result, 200) == %{}

Loading…
Cancel
Save