diff --git a/.daily_canary b/.daily_canary index 703e4e8a944..a56614de10c 100644 --- a/.daily_canary +++ b/.daily_canary @@ -1,6 +1,4 @@ - ___ ___ ___ - (- *) (O o) (O o) Y - ( V ) ( V ) ( V ) / -||/--x-m- /--m-m-----m-m---/----> -|| -|| + ___ ___ + (- *) (O o) | Y + ( V ) ( V ) O / +/--x-m- /--m-m---xXx--/ diff --git a/src/node/rpc/forwarder.h b/src/node/rpc/forwarder.h index 489b9c6c244..a36f1cdfa37 100644 --- a/src/node/rpc/forwarder.h +++ b/src/node/rpc/forwarder.h @@ -277,28 +277,26 @@ namespace ccf } const auto actor_opt = http::extract_actor(*ctx); - if (!actor_opt.has_value()) + std::optional> search; + ccf::ActorsType actor = ccf::ActorsType::unknown; + + if (actor_opt.has_value()) { - LOG_FAIL_FMT("Failed to extract actor from forwarded context."); - LOG_DEBUG_FMT( - "Failed to extract actor from forwarded context. Method is " - "'{}'", - ctx->get_method()); + const auto& actor_s = actor_opt.value(); + actor = rpc_map_shared->resolve(actor_s); + search = rpc_map_shared->find(actor); } - - const auto& actor_s = actor_opt.value(); - auto actor = rpc_map_shared->resolve(actor_s); - auto handler = rpc_map_shared->find(actor); - if (actor == ccf::ActorsType::unknown || !handler.has_value()) + if ( + !actor_opt.has_value() || actor == ccf::ActorsType::unknown || + !search.has_value()) { - LOG_FAIL_FMT("Failed to process forwarded command: unknown actor"); - LOG_DEBUG_FMT( - "Failed to process forwarded command: unknown actor {}", actor_s); - return nullptr; + // if there is no actor, proceed with the "app" as the ActorType and + // process the request + search = rpc_map_shared->find(ccf::ActorsType::users); } auto fwd_handler = - std::dynamic_pointer_cast(handler.value()); + std::dynamic_pointer_cast(search.value()); if (!fwd_handler) { LOG_FAIL_FMT( diff --git a/tests/e2e_logging.py b/tests/e2e_logging.py index e43e584a09f..4035e59abf7 100644 --- a/tests/e2e_logging.py +++ b/tests/e2e_logging.py @@ -1131,6 +1131,29 @@ def test_forwarding_frontends(network, args): return network +@reqs.description("Testing forwarding on user frontends without actor app prefix") +@reqs.at_least_n_nodes(2) +@reqs.no_http2() +def test_forwarding_frontends_without_app_prefix(network, args): + backup = network.find_any_backup() + + with backup.client("user0") as _: + check = infra.checker.Checker() + msg = "forwarded_msg" + log_id = 7 + network.txs.issue( + network, + 1, + idx=log_id, + send_public=False, + msg=msg, + private_url="/log/private", + ) + check(network.txs.request(log_id, priv=True), result={"msg": msg}) + + return network + + @reqs.description("Testing signed queries with escaped queries") @reqs.installed_package("samples/apps/logging/liblogging") @reqs.at_least_n_nodes(2) @@ -1618,6 +1641,7 @@ def additional_interfaces(local_node_id): test_clear(network, args) test_record_count(network, args) test_forwarding_frontends(network, args) + test_forwarding_frontends_without_app_prefix(network, args) test_signed_escapes(network, args) test_user_data_ACL(network, args) test_cert_prefix(network, args) diff --git a/tests/infra/logging_app.py b/tests/infra/logging_app.py index 7f80cbb50fc..6ca07a59d21 100644 --- a/tests/infra/logging_app.py +++ b/tests/infra/logging_app.py @@ -104,6 +104,7 @@ def issue( msg=None, user=None, url_suffix=None, + private_url=None, ): self.network = network remote_node, _ = network.find_primary(log_capture=log_capture) @@ -138,6 +139,7 @@ def issue( if self.scope is not None: args["scope"] = self.scope url = "/app/log/private" + url = private_url if private_url else url if url_suffix: url += "/" + url_suffix if self.scope is not None: