From ea9f89153c41b5f5cb41e663c9a8101dcbccbe3d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Sun, 21 Jun 2026 15:08:46 +0200 Subject: [PATCH 1/2] feat(engine): ignore incoming hints during phantom node lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Incoming hints are still parsed and accepted (backward compatibility), and hints are still generated in API responses. However, the server no longer uses client-provided hints to short-circuit phantom node lookups — it always performs a fresh nearest-node search instead. This prevents clients from anchoring coordinates to stale or incorrect positions while maintaining full wire-format compatibility. --- include/engine/plugins/plugin_base.hpp | 43 +------------------------- 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/include/engine/plugins/plugin_base.hpp b/include/engine/plugins/plugin_base.hpp index 3694567f73..d2a3ae71c5 100644 --- a/include/engine/plugins/plugin_base.hpp +++ b/include/engine/plugins/plugin_base.hpp @@ -10,8 +10,7 @@ #include "engine/status.hpp" #include "util/coordinate.hpp" -#include "util/coordinate_calculation.hpp" -#include "util/format.hpp" + #include "util/integer_range.hpp" #include "util/json_container.hpp" @@ -179,25 +178,11 @@ class BasePlugin parameters.coordinates.size()); BOOST_ASSERT(radiuses.size() == parameters.coordinates.size()); - const bool use_hints = !parameters.hints.empty(); const bool use_bearings = !parameters.bearings.empty(); const bool use_approaches = !parameters.approaches.empty(); for (const auto i : util::irange(0UL, parameters.coordinates.size())) { - if (use_hints && parameters.hints[i] && !parameters.hints[i]->segment_hints.empty() && - parameters.hints[i]->IsValid(parameters.coordinates[i], facade)) - { - for (const auto &seg_hint : parameters.hints[i]->segment_hints) - { - phantom_nodes[i].push_back(PhantomNodeWithDistance{ - seg_hint.phantom, - util::coordinate_calculation::greatCircleDistance( - parameters.coordinates[i], seg_hint.phantom.location)}); - } - continue; - } - phantom_nodes[i] = facade.NearestPhantomNodesInRange( parameters.coordinates[i], radiuses[i], @@ -218,7 +203,6 @@ class BasePlugin std::vector> phantom_nodes( parameters.coordinates.size()); - const bool use_hints = !parameters.hints.empty(); const bool use_bearings = !parameters.bearings.empty(); const bool use_radiuses = !parameters.radiuses.empty(); const bool use_approaches = !parameters.approaches.empty(); @@ -226,19 +210,6 @@ class BasePlugin BOOST_ASSERT(parameters.IsValid()); for (const auto i : util::irange(0UL, parameters.coordinates.size())) { - if (use_hints && parameters.hints[i] && !parameters.hints[i]->segment_hints.empty() && - parameters.hints[i]->IsValid(parameters.coordinates[i], facade)) - { - for (const auto &seg_hint : parameters.hints[i]->segment_hints) - { - phantom_nodes[i].push_back(PhantomNodeWithDistance{ - seg_hint.phantom, - util::coordinate_calculation::greatCircleDistance( - parameters.coordinates[i], seg_hint.phantom.location)}); - } - continue; - } - phantom_nodes[i] = facade.NearestPhantomNodes( parameters.coordinates[i], number_of_results, @@ -262,7 +233,6 @@ class BasePlugin { std::vector alternatives(parameters.coordinates.size()); - const bool use_hints = !parameters.hints.empty(); const bool use_bearings = !parameters.bearings.empty(); const bool use_radiuses = !parameters.radiuses.empty(); const bool use_approaches = !parameters.approaches.empty(); @@ -271,17 +241,6 @@ class BasePlugin BOOST_ASSERT(parameters.IsValid()); for (const auto i : util::irange(0UL, parameters.coordinates.size())) { - if (use_hints && parameters.hints[i] && !parameters.hints[i]->segment_hints.empty() && - parameters.hints[i]->IsValid(parameters.coordinates[i], facade)) - { - std::transform(parameters.hints[i]->segment_hints.begin(), - parameters.hints[i]->segment_hints.end(), - std::back_inserter(alternatives[i].first), - [](const auto &seg_hint) { return seg_hint.phantom; }); - // we don't set the second one - it will be marked as invalid - continue; - } - alternatives[i] = facade.NearestCandidatesWithAlternativeFromBigComponent( parameters.coordinates[i], use_radiuses ? parameters.radiuses[i] : default_radius, From 98d0fc60253df40e6baa0190cdbb62f28917634f Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Sun, 21 Jun 2026 16:59:17 +0200 Subject: [PATCH 2/2] feat(engine): ignore incoming hints during phantom node lookup Incoming hints are still parsed and accepted (backward compatibility), and hints are still generated in API responses. However, the server no longer uses client-provided hints to short-circuit phantom node lookups - it always performs a fresh nearest-node search instead. - Removed hint-usage logic from all three GetPhantomNodes overloads - Added explicit #include (previously transitive via util/format.hpp) - Added cucumber regression test for bogus/empty hints --- features/testbot/hints.feature | 57 ++++++++++++++++++++++++++ include/engine/plugins/plugin_base.hpp | 1 + 2 files changed, 58 insertions(+) create mode 100644 features/testbot/hints.feature diff --git a/features/testbot/hints.feature b/features/testbot/hints.feature new file mode 100644 index 0000000000..a9c718c83c --- /dev/null +++ b/features/testbot/hints.feature @@ -0,0 +1,57 @@ +@routing @testbot +Feature: Hints handling - incoming hints are ignored but still generated + + Background: + Given the profile "testbot" + Given a grid size of 100 meters + + Scenario: Normal routing works without hints + Given the node map + """ + a b + """ + + And the ways + | nodes | + | ab | + + When I route I should get + | from | to | route | + | a | b | ab,ab | + | b | a | ab,ab | + + Scenario: Route with bogus hints is accepted and produces correct result + Given the node map + """ + a b + """ + + And the ways + | nodes | + | ab | + + Given the query options + | hints | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | + + When I route I should get + | from | to | route | status | + | a | b | ab,ab | 200 | + | b | a | ab,ab | 200 | + + Scenario: Route with empty hints parameter is accepted + Given the node map + """ + a b + """ + + And the ways + | nodes | + | ab | + + Given the query options + | hints | ; | + + When I route I should get + | from | to | route | status | + | a | b | ab,ab | 200 | + | b | a | ab,ab | 200 | diff --git a/include/engine/plugins/plugin_base.hpp b/include/engine/plugins/plugin_base.hpp index d2a3ae71c5..1e29f6d233 100644 --- a/include/engine/plugins/plugin_base.hpp +++ b/include/engine/plugins/plugin_base.hpp @@ -15,6 +15,7 @@ #include "util/json_container.hpp" #include +#include #include #include #include