Class HandlerContext
Defined in File handler_context.hpp
Class Documentation
-
class HandlerContext
Shared context for all HTTP handlers.
Provides access to gateway node, configuration, and common utilities that handlers need to process requests.
Public Functions
-
inline HandlerContext(GatewayNode *node, const CorsConfig &cors_config, const AuthConfig &auth_config, const TlsConfig &tls_config, AuthManager *auth_manager, BulkDataStore *bulk_data_store = nullptr)
-
inline GatewayNode *node() const
Get gateway node.
-
inline const CorsConfig &cors_config() const
Get CORS configuration.
-
inline const AuthConfig &auth_config() const
Get authentication configuration.
-
inline AuthManager *auth_manager() const
Get authentication manager (may be nullptr if auth disabled)
-
inline BulkDataStore *bulk_data_store() const
Get bulk data store (may be nullptr if not configured)
-
inline void set_aggregation_manager(AggregationManager *mgr)
Set the aggregation manager (non-owning, null when aggregation disabled)
-
inline AggregationManager *aggregation_manager() const
Get the aggregation manager (may be nullptr if aggregation disabled)
-
tl::expected<void, std::string> validate_entity_id(const std::string &entity_id) const
Validate entity ID (component_id, area_id, etc.)
- Parameters:
entity_id – The ID to validate
- Returns:
Empty if valid, error message otherwise
-
tl::expected<std::string, std::string> get_component_namespace_path(const std::string &component_id) const
Get namespace path for a component.
- Deprecated:
Use get_entity_info instead for unified entity handling
- Parameters:
component_id – Component ID
- Returns:
Namespace path or error message
-
EntityInfo get_entity_info(const std::string &entity_id, SovdEntityType expected_type = SovdEntityType::UNKNOWN) const
Get information about any entity (Component, App, Area, Function)
If expected_type is specified, searches ONLY in that collection. If expected_type is UNKNOWN (default), searches all types in order: Component, App, Area, Function - returns the first match found.
- Parameters:
entity_id – Entity ID to look up
expected_type – Optional: restrict search to specific entity type
- Returns:
EntityInfo with resolved details, or EntityInfo with UNKNOWN type if not found
-
tl::expected<void, ErrorInfo> validate_lock_access(const http::TypedRequest &req, const EntityInfo &entity, const std::string &collection)
Validate lock access for a mutating operation.
Two-phase check:
If locking disabled (no LockManager), allows access.
Extracts X-Client-Id header, checks LockManager::check_access().
On denial, returns a populated ErrorInfo (HTTP 409 with either ERR_LOCK_BROKEN or ERR_INVALID_REQUEST). The method never touches an httplib::Response; the typed router serializes the ErrorInfo onto the wire. Locking is always local, so there is no Forwarded variant.
- Parameters:
req – Typed HTTP request (for X-Client-Id header).
entity – Entity being accessed.
collection – Resource collection being mutated (e.g. “configurations”).
- Returns:
Empty success on allow, ErrorInfo on denial.
-
http::ValidatorResult<EntityInfo> validate_entity_for_route(const http::TypedRequest &req, const std::string &entity_id) const
Validate entity exists and matches expected route type (typed variant).
Unified validation helper that:
Validates the entity ID format.
Looks up the entity in the expected collection (based on route path).
For remote entities (aggregation), forwards the request to the peer gateway, writes the proxied response to the underlying httplib::Response, and returns Forwarded so the caller knows the wire is committed.
On local failure, returns a populated ErrorInfo without touching the response. The typed router serializes the error.
The success branch carries the resolved EntityInfo. The error branch is a variant of:
ErrorInfo - local validation failure (400 invalid-parameter, 404 entity-not-found). Caller serializes via write_generic_error.
Forwarded - request was proxied to a peer; the response is already written and the caller must return immediately without touching the response further.
The Forwarded path is the one place the validator still mutates the underlying httplib::Response. Aggregation could not be modeled cleanly any other way without either (a) returning the proxied bytes as a buffered payload (loses streaming and headers) or (b) exposing the response object to the caller (defeats the typed surface). Keeping the proxy write inside the validator preserves the historical aggregation behavior bit-for-bit.
- Parameters:
req – Typed HTTP request (used to extract expected type from path and to drive the forward proxy).
entity_id – Entity ID to validate.
- Returns:
EntityInfo on local success, or an error variant indicating local failure (ErrorInfo) vs. peer forwarding completed (Forwarded).
-
void set_cors_headers(httplib::Response &res, const std::string &origin) const
Set CORS headers on response if origin is allowed.
- Parameters:
res – HTTP response
origin – Origin header value
-
bool is_origin_allowed(const std::string &origin) const
Check if origin is allowed by CORS config.
- Parameters:
origin – Origin header value
- Returns:
true if allowed
Public Static Functions
-
static tl::expected<void, ErrorInfo> validate_collection_access_typed(const EntityInfo &entity, ResourceCollection collection)
Validate that entity supports a resource collection (typed variant).
Returns a populated ErrorInfo (HTTP 400, ERR_COLLECTION_NOT_SUPPORTED) when the entity type does not support the collection. The typed router serializes the error onto the wire; this method never touches an httplib::Response.
- Parameters:
entity – Entity information (from get_entity_info)
collection – Resource collection to validate
- Returns:
Empty success on support, ErrorInfo on rejection.
-
static inline ErrorInfo forwarded_sentinel_error()
Build the framework-internal sentinel error that typed handlers return after the validator’s Forwarded path already committed the proxied wire response.
Typed handlers use this helper so the typed
Result<T>shape can propagate the validator’sForwardedvariant without re-rendering the body. The wrapper in RouteRegistry detects the sentinel via its error code (ERR_X_INTERNAL_FORWARDED) and skips error rendering.- Returns:
ErrorInfo with the sentinel code and
http_status == 0.
-
static inline rclcpp::Logger logger()
Get logger for handlers.
-
static std::vector<std::string> resolve_app_host_fqns(const ThreadSafeEntityCache &cache, const std::vector<std::string> &app_ids)
Resolve a list of app IDs to their non-empty effective FQNs.
Apps that are missing from the cache or that have an empty effective_fqn() are skipped silently. The returned vector preserves the input app_ids order (minus skipped entries) and may be empty. Apps whose effective_fqn() is already present in the result are skipped, so duplicates from manifest / runtime double-binds do not produce repeated downstream queries.
Used by log_handlers and bulkdata_handlers to aggregate per-component / per-function resource queries from the entity’s hosted apps. Static + public to enable direct unit testing without standing up a full GatewayNode fixture.
- Parameters:
cache – Entity cache to look up apps in
app_ids – App IDs to resolve
- Returns:
Effective FQNs for the apps that resolved
-
static std::set<std::string> resolve_entity_source_fqns(const ThreadSafeEntityCache &cache, const EntityInfo &entity)
Resolve an entity to the set of source FQNs it owns.
Returns the FQNs of every ROS 2 node within the entity’s scope. Used by fault handlers to filter
reporting_sourcesso that per-entity routes never expose faults reported from outside the addressed entity.Mapping per entity type:
App: the app’s
effective_fqn()(single entry, or empty set if unbound or ifros_binding.namespace_patternis a wildcard - by designeffective_fqn()returns “” for those, so the entity simply has no addressable ROS node and the scope check excludes every fault).Component:
effective_fqn()of every hosted app viaget_apps_for_component().Area:
effective_fqn()of every app under the area, walkingget_subareas()recursively so nested areas (e.g.powertrain -> engine) resolve to the union of their descendants’ apps.Function:
effective_fqn()of every app the function hosts directly plus, for hosts that are component IDs, the apps inside those components.Unknown: empty set.
Apps whose
effective_fqn()is empty are silently dropped from the set so the scope check cannot match arbitrary FQNs against an empty prefix.An empty result means “no apps are in scope” and callers must NEVER interpret that as “no filter” - any fault must be treated as out of scope. The exact response (404 for per-fault routes, an empty
itemsarray for collection lists, 204 for collection clears) is up to the caller.- Parameters:
cache – Entity cache for lookups
entity – Resolved entity info (from
validate_entity_for_route)
- Returns:
Set of FQNs that uniquely scopes faults to this entity
-
inline HandlerContext(GatewayNode *node, const CorsConfig &cors_config, const AuthConfig &auth_config, const TlsConfig &tls_config, AuthManager *auth_manager, BulkDataStore *bulk_data_store = nullptr)