message_router.rs
Overview
This file implements a MessageRouter that acts as a web server endpoint for receiving, authenticating, and forwarding external messages to a business process (BP) system. It leverages the actix_web framework to expose HTTP services for inbound messages, handles authorization tokens, and manages key cryptographic signing credentials. The router provides asynchronous processing of JSON-based messages, implements token issuance for authenticated requests, and manages internal state via thread-safe synchronization.
The main responsibilities include:
Binding to a network socket address and listening for incoming HTTP requests.
Accepting and verifying JSON messages with embedded authorization tokens.
Forwarding valid messages to the BP resolver component.
Optionally signing and issuing authentication tokens using configured cryptographic keys.
Providing a configurable web service with middleware for logging and default headers.
Structures and Implementations
MessageRouterConfig
pub struct MessageRouterConfig {
pub bp_resolver: Arc<Mutex<dyn BPResolver>>,
pub owner_wallet_pubkey: Option<String>,
pub signing_keys: Option<KeyPair>,
}
Purpose: Configuration container used to initialize a
MessageRouterinstance.Fields:
bp_resolver: Thread-safe shared reference to an implementation of theBPResolvertrait, responsible for business process resolution.owner_wallet_pubkey: Optional public key string representing the wallet owner.signing_keys: Optional cryptographic key pair used to sign tokens.
MessageRouter
#[derive(Clone)]
pub struct MessageRouter {
pub bind: SocketAddr,
pub owner_wallet_pubkey: Option<String>,
pub signing_keys: Option<KeyPair>,
pub bp_resolver: Arc<Mutex<dyn BPResolver>>,
}
Purpose: Main router entity that holds state and configuration for processing external messages.
Fields:
bind: Network socket address where the HTTP server listens.owner_wallet_pubkey: Optional owner wallet public key.signing_keys: Optional cryptographic key pair used for token signing.bp_resolver: Shared reference to the BP resolver instance.
Display implementation for MessageRouter
Provides a human-readable string representation primarily for logging purposes.
impl Display for MessageRouter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "MessageRouter bind={}", self.bind)
}
}
MessageRouter Associated Functions and Methods
new
pub fn new(bind: String, config: MessageRouterConfig) -> Self
Description: Constructs a new
MessageRouterinstance given a bind address string and a configuration object.Parameters:
bind: String representing the network address and port to bind to (e.g.,"127.0.0.1:8080").config:MessageRouterConfigcontaining resolver, keys, and owner info.
Returns: New
MessageRouterinstance with parsed socket address.Usage example:
let config = MessageRouterConfig { bp_resolver: Arc::new(Mutex::new(my_bp_resolver)), owner_wallet_pubkey: Some("owner_pubkey".to_string()), signing_keys: Some(my_keypair), }; let router = MessageRouter::new("127.0.0.1:8080".to_string(), config);Implementation details: Uses
to_socket_addrs()to resolve the bind string into aSocketAddr. Logs startup info.
config
pub fn config(cfg: &mut web::ServiceConfig, message_router: Arc<MessageRouter>)
Description: Configures the Actix web service routes and middleware for the router.
Parameters:
cfg: Mutable reference to Actix'sServiceConfigfor setting up routes.message_router: SharedArcpointer to theMessageRouterinstance.
Functionality:
Registers a POST route at the path defined by the environment variable
ROUTER_URL_PATH(default fallback).This route expects JSON payloads representing an array of messages with tokens.
Routes POST requests to the asynchronous handler
actix_ext_messages_handler.Responds with
MethodNotAllowedfor HEAD requests on the same path.
Message Format: JSON array of objects with fields such as
"id","body", optional"expireAt", optional"threadId", and nested"ext_message_token"containing unsigned message and signature.
dump
pub fn dump(&self)
Description: Logs the current state of the router at debug verbosity.
Usage: Useful for diagnostics or internal state inspection.
issue_token
pub fn issue_token(&self) -> Option<Token>
Description: Issues a cryptographic authentication token when signing keys and owner wallet public key are available.
Returns:
Some(Token)if signing keys and owner pubkey exist and token creation succeeds.Noneif keys or pubkey are missing.
Implementation details:
Constructs a new
Tokenwith the secret key and issuer information.Uses
ext_messages_auth::auth::Tokenfunctionality.
Example usage:
if let Some(token) = router.issue_token() { // Use token for authenticated requests }
run
pub fn run(&self)
Description: Starts the Actix web server in a dedicated thread.
Implementation details:
Clones the
MessageRouterinstance into anArc.Spawns a new thread named "Message router".
Calls the asynchronous
runfunction to launch the HTTP server.Logs any server errors that cause the thread to exit.
Usage: Called to activate the router and begin listening for incoming requests.
Asynchronous Functions
run
#[actix_web::main]
async fn run(message_router: Arc<MessageRouter>) -> anyhow::Result<()>
Description: Asynchronous function to initialize and run the Actix HTTP server.
Parameters:
message_router: SharedArcpointer to the router instance.
Functionality:
Binds the server to the
SocketAddrstored inmessage_router.Configures the Actix
Appwith middleware, including default headers (Content-type: application/json) and logger.Applies router configuration for routes.
Runs the server asynchronously and awaits termination.
Returns: Result indicating success or error wrapped in
anyhow::Result.Implementation notes: Uses
HttpServer::newclosure to clonemessage_routerfor each worker thread.
actix_ext_messages_handler
async fn actix_ext_messages_handler(
node_requests: web::Json<serde_json::Value>,
message_router: Arc<MessageRouter>,
) -> actix_web::Result<web::Json<serde_json::Value>>
Description: Asynchronous handler for processing incoming external messages.
Parameters:
node_requests: JSON payload representing the external messages.message_router: Shared router instance for forwarding and token verification.
Functionality:
Invokes
crate::process_ext_messages::runpassing the deserialized JSON and router.Returns processed JSON response on success.
Logs errors and returns HTTP 500 Internal Server Error on failure.
Interaction: Acts as the main point of integration between incoming HTTP requests and internal message processing logic.
Implementation Details and Algorithms
The router uses lazy static variables
NODE_URL_PATHandROUTER_URL_PATHto configure endpoint paths from environment variables, falling back to default constants.Messages are expected in a JSON array format with embedded authentication tokens conforming to a specific schema.
Token issuance relies on the presence of signing keys and owner wallet public key; it creates signed tokens using the
ext_messages_authcrate.The HTTP server is spawned on a separate thread to avoid blocking the main application flow.
The router uses
Arc<Mutex<dyn BPResolver>>to share the business process resolver safely across threads and asynchronous contexts.The
actix_webmiddleware stack includes logging and default response headers to enforce consistent content types.Error handling in the message processing handler converts internal errors to HTTP 500 responses and logs them for observability.
Interactions with Other System Components
BPResolver (
bp_resolver): The router relies on a thread-safe, trait-object resolver to delegate business logic processing of inbound messages.KeyPair: Cryptographic key pairs are used to sign tokens for authenticating message sources.
Ext Messages Auth (
ext_messages_auth::auth): Provides token creation, verification, and issuer identification.Process Ext Messages Module (
crate::process_ext_messages): Contains the core asynchronous logic to validate and forward messages; invoked by the HTTP handler.Defaults Module (
crate::defaults): Supplies default URL paths used by the router.Actix Web Framework: Manages HTTP server lifecycle, routing, middleware, and asynchronous request handling.
Visual Diagram
flowchart TD
A[MessageRouter::run] --> B[Spawn Thread]
B --> C[run async fn]
C --> D[HttpServer::new]
D --> E[App Configuration]
E --> F[Middleware: Logger & Headers]
E --> G[MessageRouter::config]
G --> H[Route: POST ROUTER_URL_PATH]
H --> I[actix_ext_messages_handler]
I --> J[process_ext_messages::run]
J -->|Uses| K["BPResolver (Arc<Mutex>)"]
I -->|Uses| L[MessageRouter instance]
MessageRouter --> M[issue_token]
M --> N[Token creation]
The diagram illustrates the flow from starting the router, configuring the HTTP server, handling routes, processing messages via the BPResolver, and issuing tokens.
Arrows indicate method calls and dependencies between components within this file.
Environment Configuration
NODE_URL_PATH: Environment variable controlling the node URL path; falls back toDEFAULT_NODE_URL_PATH.ROUTER_URL_PATH: Environment variable controlling the router URL path; falls back toDEFAULT_URL_PATH.
Usage Example
use std::sync::Arc;
use parking_lot::Mutex;
// Assume BPResolver implementation and KeyPair initialization
let bp_resolver = Arc::new(Mutex::new(my_bp_resolver));
let config = MessageRouterConfig {
bp_resolver,
owner_wallet_pubkey: Some("owner_pubkey_string".to_string()),
signing_keys: Some(my_keypair),
};
let router = MessageRouter::new("0.0.0.0:8080".to_string(), config);
router.run(); // Starts the server and listens for incoming messages
This example shows basic setup and startup of the message router server binding to all interfaces on port 8080.