rest_api_routes.rs
Overview
This source file defines the REST API routing and corresponding handlers for key endpoints related to account data retrieval, message processing, and service readiness checks. It leverages asynchronous handlers within the Salvo web framework to manage incoming HTTP requests, interact with internal application state (AppState), and produce appropriate HTTP responses. The file primarily serves as the interface layer between external clients and the internal business logic encapsulated by the message router and blockchain data fetcher.
Public Functions and Handlers
rest_api_router
pub fn rest_api_router(app_state: Arc<AppState>) -> Router
Purpose: Constructs and returns a
Routerconfigured with the REST API endpoints under the/v2path prefix.Parameters:
app_state: Arc<AppState>- Shared, thread-safe application state injected into all routes.
Returns: A
Routerinstance with the following routes configured:GET /v2/account→ fetches BOC (Bag of Cells) data by blockchain address.GET /v2/readiness→ readiness check endpoint.POST /v2/messages→ endpoint to process external messages.
Usage Example:
let app_state = Arc::new(AppState::new(...)); let router = rest_api_router(app_state); // Use router with HTTP serverImplementation Details:
Uses
affix_state::injectto inject shared state into routes.No authentication middleware is enabled currently (commented out).
Routes are set up using
Router::with_pathand appended via.push().
route_message Handler
#[handler]
async fn route_message(req: &mut Request, depot: &mut Depot, res: &mut Response)
Purpose: Handles POST requests to
/v2/messagesto process external messages via the internal message router.Parameters:
req: &mut Request- Incoming HTTP request, expected to have a JSON body.depot: &mut Depot- Dependency injection container for extracting shared state.res: &mut Response- HTTP response to be populated.
Returns: None directly; sends HTTP response with status and JSON body or error message.
Behavior:
Extracts
Arc<AppState>fromDepot.Parses JSON body from the request.
Passes parsed JSON and message router instance to
process_ext_messages::run.On success, returns HTTP 200 with JSON response.
On failure, logs error and responds with HTTP 500 or 400 as appropriate.
Usage Example: Client sends JSON message to
/v2/messagesto trigger message processing.
boc_by_address Handler
#[handler]
async fn boc_by_address(req: &mut Request, depot: &mut Depot, res: &mut Response)
Purpose: Handles GET requests to
/v2/accountto fetch the Bag of Cells (BOC) data associated with a blockchain account address.Parameters:
req: &mut Request- Incoming HTTP request, expecting query parameteraddress.depot: &mut Depot- Dependency container for app state.res: &mut Response- HTTP response to be populated.
Returns: None directly; forwards the fetched BOC as HTTP response body or returns error status.
Behavior:
Obtains shared
AppState.Retrieves and validates the
addressquery parameter.Rejects requests missing
addressor with invalid format.
Constructs a BOC fetch request via
build_fetch_boc_request.Sends an asynchronous HTTP request to the default blockchain proxy (
default_bp).Forwards response status and body transparently to the client.
Handles errors such as request failure or body reading failure with appropriate HTTP error codes.
Implementation Details:
Uses
AccountId::from_stringfor address validation.Does not forward response headers except for status and body.
Usage Example: Client queries
/v2/account?address=0:abcdef...to get the BOC for that address.
readiness Handler
#[handler]
async fn readiness(_req: &mut Request, depot: &mut Depot, res: &mut Response)
Purpose: Provides a health check endpoint at
/v2/readinessto indicate if the service is ready based on recent block generation activity.Parameters:
_req: &mut Request- Incoming HTTP request (unused).depot: &mut Depot- Dependency container to obtain shared state.res: &mut Response- HTTP response to be populated.
Returns: None directly; responds with HTTP 200 if ready, 503 otherwise, with diagnostic info.
Behavior:
Obtains
AppState.Reads
last_block_gen_utimeatomic timestamp (in milliseconds).Compares current time to last block generation time.
If difference less than threshold (
HEALTH_GEN_UTIME_DIFF_SECseconds), responds with HTTP 200 OK.Otherwise, responds with HTTP 503 Service Unavailable.
Response body contains readiness status and timing details.
Usage Example: Used by load balancers or orchestrators to check service health.
render_error Utility Function
fn render_error(res: &mut Response, status_code: StatusCode, text: &str)
Purpose: Helper to populate the HTTP response with an error status and message.
Parameters:
res: &mut Response- Response object to modify.status_code: StatusCode- HTTP error status code to set.text: &str- Error message body.
Returns: None.
Usage: Called internally by handlers to send error responses consistently.
Important Implementation Details
State Injection: The shared application state (
AppState) is injected into handlers using Salvo's depot mechanism combined withaffix_state::inject. This allows handlers to access internal resources like the message router and the default blockchain proxy.Atomic Timestamp: The readiness check uses an atomic
last_block_gen_utimetimestamp to safely share the time of the last generated block across threads.Address Validation: The blockchain account address is validated using
AccountId::from_stringensuring only correctly formatted addresses are accepted.External Request Forwarding: The BOC fetch endpoint acts as a proxy forwarding the blockchain data fetch request to a backend service and streaming the response back to the client, preserving status codes but not headers.
Error Handling: Handlers use the
render_errorfunction to return consistent error responses and log detailed error messages for diagnostics.Asynchronous Processing: All handlers are asynchronous, enabling non-blocking I/O operations for request parsing, external HTTP calls, and response writing.
Interaction with Other System Components
AppState: Central shared state containing:
message_routerfor processing external messages.default_bprepresenting the blockchain proxy endpoint used to fetch BOC data.last_block_gen_utimeatomic variable for health monitoring.
process_ext_messagesModule: Invoked withinroute_messageto handle JSON message payloads asynchronously.build_fetch_boc_requestFunction (frombm_contract_root): Used to create HTTP requests for fetching BOC data from the blockchain proxy.tvm_types::AccountId: Utilized for blockchain account address validation.telemetry_utils::now_ms: Provides current timestamp in milliseconds for readiness calculations.salvo::prelude::*: Provides web framework utilities such asRouter,Request,Response, and attribute macros for handlers.
This file acts as the API layer connecting external HTTP clients to internal blockchain logic and message processing services.
Diagram: REST API Router and Handler Workflow
flowchart TD
REST_API_ROUTER["rest_api_router"]
ROUTE_MESSAGE["route_message\n(POST /v2/messages)"]
BOC_BY_ADDRESS["boc_by_address\n(GET /v2/account)"]
READINESS["readiness\n(GET /v2/readiness)"]
APP_STATE["AppState\n(shared state)"]
MESSAGE_ROUTER["message_router"]
BLOCKCHAIN_PROXY["default_bp\n(blockchain proxy)"]
PROCESS_EXT_MSG["process_ext_messages::run"]
BUILD_BOC_REQ["build_fetch_boc_request"]
REST_API_ROUTER --> ROUTE_MESSAGE
REST_API_ROUTER --> BOC_BY_ADDRESS
REST_API_ROUTER --> READINESS
ROUTE_MESSAGE --> APP_STATE
ROUTE_MESSAGE --> MESSAGE_ROUTER
ROUTE_MESSAGE --> PROCESS_EXT_MSG
BOC_BY_ADDRESS --> APP_STATE
BOC_BY_ADDRESS --> BUILD_BOC_REQ
BUILD_BOC_REQ --> BLOCKCHAIN_PROXY
READINESS --> APP_STATE
The router exposes three endpoints.
Handlers obtain shared state (
AppState).route_messagedelegates JSON message processing toprocess_ext_messages::run.boc_by_addressbuilds and sends requests to the blockchain proxy.readinessuses atomic timestamps from state to determine service health.