Loading…
Loading…
Technical documentation for the Runtime Controller, which processes all inbound API traffic, including REST-to-SOAP, SOAP-to-REST, and SOAP passthrough
The Runtime Controller is the central HTTP entry point for all API traffic processed by the platform. It acts as a sophisticated gateway, receiving requests from API consumers, applying security and transformation logic, dispatching them to the appropriate backend services, and returning responses.
The controller is responsible for several key functions:
direction (e.g., publish, consume, gateway), environment, and serviceKey. It uses this information to look up the correct route configuration via the RuntimeRouteCacheService.GatewayIngressGuard) to ensure requests originate from trusted network paths.ConsumerIpGrantGuard) to restrict service access to authorized client IPs.active_passive, round_robin), performs health checks to filter out unhealthy backends, and manages authentication to those backends./health/live, /health/ready) and performs detailed, structured logging for every transaction via the RuntimeLogAsyncWriter.All API requests are assigned a unique correlationId (either from the X-Correlation-Id header or generated by the controller) to facilitate end-to-end tracing.
The controller handles three primary data flow directions: publish, gateway, and consume.
The publish flow exposes a SOAP backend as a modern RESTful API. The controller receives a JSON request, converts it to a SOAP envelope, calls the backend SOAP service, and transforms the SOAP response back into a JSON response for the client.
flowchart TD
subgraph API Consumer
A[Client sends REST Request]
end
subgraph Runtime Controller
B[POST /{direction}/{env}/**]
C{Route Resolution}
D{Schema & Regex Validation}
E[JSON to SOAP Conversion]
F{Async or Sync?}
G[Send SOAP to Backend]
H[Receive SOAP Response]
I[SOAP to JSON Conversion]
J{Response Validation}
K[Shape Response (Envelope/Error)]
end
subgraph Backend
L[SOAP Backend Service]
end
subgraph Logging
M[Async Log Writer]
end
A --> B
B --> C
C -- Found --> D
C -- Not Found --> K
D -- Valid --> E
D -- Invalid --> K
E --> F
F -- Sync --> G
F -- Async --> G
G --> L
L --> H
H --> I
I --> J
J -- Valid --> K
J -- Invalid --> K
K --> A
B -- All Paths --> M
K -- All Paths --> MPOST) to /publish/{environment}/{serviceKey}/{operationKey}.404 Not Found error. It includes a defensive check to correct for misconfigured upstream gateways that may send a duplicated /{environment}/{serviceKey} prefix.503 Service Unavailable error.OpenApiSchemaValidationInterceptor. Invalid requests are rejected with a 400 Bad Request (S2R-VAL-0410).request_field_validation_regexes) are enforced by FieldRegexValidator. Mismatches are rejected with a 400 Bad Request (S2R-VAL-0411).requestTransformRules.SoapMessageMapper, honoring the operation's configured soapOperationName, soapNamespace, and soapVersion.async_callback): The controller injects WS-Addressing headers into the SOAP request, creates a pending record in the async_execution table, and sends the request. It immediately returns a 202 Accepted response to the consumer with a correlationId and a path for polling the result.faultDetailExposureMode.502 Bad Gateway (S2R-VAL-0430 or S2R-VAL-0431), as the backend has returned a non-compliant response.envelopeWrapOverride and errorShapeOverride settings and returned to the API consumer.RuntimeLogAsyncWriter to be persisted.The gateway flow acts as a high-fidelity SOAP passthrough broker. It is designed to be a drop-in replacement for a direct backend connection, preserving the SOAP envelope bytes and applying critical security checks.
IMPORTANT
The gateway data path is handled by a dedicated POST /gateway/{environment}/** mapping. This is crucial for preserving the raw byte stream of the request body, which would be destroyed by the character decoding that occurs in the main /{direction}/** mapping. A request to /gateway that incorrectly lands in the main mapping will be rejected with a 500 Internal Server Error to prevent silent data corruption.
flowchart TD
subgraph API Consumer
A[Client sends SOAP Request]
end
subgraph Runtime Controller
B[POST /gateway/{env}/**]
C[Ingress Guard]
D{Route Resolution}
E[Consumer IP Grant Guard]
F[Read Raw Body Bytes]
G[Select Backend]
H[Forward Raw Body]
end
subgraph Backend
I[SOAP Backend Service]
end
A --> B
B --> C
C -- Deny --> A
C -- Allow --> D
D -- Found --> E
D -- Not Found --> A
E -- Deny --> A
E -- Allow --> F
F --> G
G --> H
H --> I
I --> H
H --> APOST request with a SOAP payload to /gateway/{environment}/{serviceKey}.GatewayIngressGuard immediately evaluates the request's origin. It checks the X-Forwarded-For header against a configured list of trusted proxies. If the request does not come from a trusted path, it is rejected with a 403 Forbidden before its body is read or processed./gateway/{environment}/{serviceKey}) only. The SOAP payload or SOAPAction header is not used for routing.ConsumerIpGrantGuard checks if the attributed client IP address is explicitly granted access to this service. If not, the request is rejected with a 403 Forbidden, also before the body is read.GatewaySoapHandler forwards the original request body bytes to the backend. It rebuilds security-sensitive headers like X-Forwarded-For based on the trusted, derived client address, rather than relaying the inbound values.Authorization are redacted, and payloads are not logged unless debug mode is enabled.The consume flow exposes a modern REST/JSON backend as a standard SOAP web service. This allows legacy SOAP clients to integrate with services that only speak REST.
POST request to /consume/{environment}/{serviceKey}.POST and that the Content-Type is appropriate for a SOAP request.SOAPAction header to disambiguate operations that share an endpoint address.requestMapping. This process handles xop:Include for MTOM attachments, inlining them into the SOAP envelope before parsing.basic, bearer, and api_key_header.ConsumeSoapHandler dispatches the corresponding REST request (e.g., GET, POST) to the backend, including the generated JSON payload and authentication headers.For long-running publish operations, the controller supports an asynchronous callback pattern.
Initiation: An API consumer makes a publish request to an operation configured with executionMode set to async_callback.
202 Accepted response. The response body contains a correlationId, a pollPath for checking status, and a single-use pollToken. The token is also returned in the X-S2R-Poll-Token header.AsyncExecutionRecord is created in the database with a status of waiting_callback.Polling: The consumer can poll the status by making a GET request to the pollPath (/{direction}/{...}/async/{correlationId}).
X-S2R-Poll-Token header received during initiation.waiting_callback, completed, failed, expired). If completed, the final result payload is included.Callback: The backend SOAP service completes its processing and sends the result in a SOAP response to a special callback endpoint: POST /_s2r/callback/{environment}/{serviceKey}/{operationKey}.
RelatesTo or MessageID) that matches the original correlationId.callback_auth_mode is shared_secret, the callback must provide the correct secret in the X-S2R-Callback-Secret or Authorization: Bearer header. Unauthenticated callbacks are rejected with a 401 Unauthorized.AsyncExecutionRecord with the result and sets the status to completed or failed.409 Conflict.The controller can serve a WSDL contract for consume and gateway services, which is essential for SOAP client tooling. A WSDL is requested by appending ?wsdl to the service's base URL or by appending a /wsdl path segment.
GET /consume/{env}/{serviceKey}?wsdl or GET /gateway/{env}/{serviceKey}?wsdlgateway services, it first applies the GatewayIngressGuard and ConsumerIpGrantGuard to ensure only authorized clients can discover the service's topology.runtimeWsdlRepository.<soap:address location="..."> attribute in the WSDL to point to the public-facing URL of the platform itself. This ensures that client stubs generated from the WSDL will send requests back to the platform, not to the original backend address.Content-Type of application/wsdl+xml.The controller enforces security and data integrity at multiple stages of the request lifecycle.
| Guard / Validator | Direction(s) | Trigger | Action on Failure |
|---|---|---|---|
GatewayIngressGuard | gateway | Request to a gateway path. | 403 Forbidden. Denies before body read. |
ConsumerIpGrantGuard | gateway | Request to a gateway path after route resolution. | 403 Forbidden. Denies before body read. |
OpenApiSchemaValidationInterceptor | publish | Request or response payload processing. | 400 Bad Request (request) or 502 Bad Gateway (response). |
FieldRegexValidator | publish | Request or response payload processing. | 400 Bad Request (request) or 502 Bad Gateway (response). |
| Callback Authentication | publish (async) | Inbound request to the async callback endpoint. | 401 Unauthorized. |
| License Enforcement | All | Request to /health/ready. | 503 Service Unavailable if license state is RUNTIME_STOP. |
When a route has multiple backend targets, the controller uses a defined strategy to select one.
Routing Mode (backendRoutingMode):
single: Only the preferred backend (by defaultBackendProfileId or lowest routingPriority) is used.active_passive: Tries backends in order of routingPriority. The first successful one is used.round_robin: Distributes requests across all healthy backends according to their routingWeight.Health Checks (backendHealthCheckMode):
backendHealthCheckIntervalSec.none: No health checks are performed.ping: An ICMP ping to the backend host.tcp: A TCP connection test to the backend's host and port.wsdl_fetch: An HTTP GET to the backend's WSDL or health check URL. This can include semantic validation to ensure the WSDL still contains the required operation and namespace.The controller generates structured JSON error responses. The exact shape is configurable via the errorShapeOverride setting.
| Status | Code | Description |
|---|---|---|
| 400 | S2R-RUN-0405 | The request URL is missing or has an invalid direction segment (e.g., /publish/). |
| 400 | S2R-VAL-0400 | General bad request, such as invalid JSON or an unusable X-Correlation-Id for an async operation. |
| 400 | S2R-VAL-0410 | The request body failed validation against the configured OpenAPI schema. |
| 400 | S2R-VAL-0411 | A field in the request body failed validation against a configured regex pattern. |
| 401 | S2R-RUN-0401 | Authentication failed, typically for an asynchronous callback. |
| 403 | S2R-GW-0403 | Gateway ingress denied by GatewayIngressGuard. |
| 403 | S2R-GW-0407 | Gateway access denied by ConsumerIpGrantGuard. |
| 404 | S2R-RUN-0404 | No route or resource could be found for the request path. |
| 405 | S2R-RUN-0411 | The HTTP method is not supported for the endpoint (e.g., GET on a POST-only gateway path). |
| 409 | S2R-RUN-0431 | A callback was received for an asynchronous execution that has already been completed or failed. |
| 410 | S2R-RUN-0410 | An asynchronous execution expired before it could be completed. |
| 413 | S2R-RUN-0413 | The request or response payload exceeded the maximum allowed size. |
| 500 | S2R-RUN-0500 | An internal server error occurred, such as a gateway mapping precedence failure. |
| 502 | S2R-RUN-0502 | The backend service returned a SOAP Fault or a non-2xx HTTP status. |
| 502 | S2R-RUN-0504 | The runtime failed to parse the SOAP response from the backend. |
| 502 | S2R-RUN-0505 | The configuration for authenticating to the backend is invalid or missing credentials. |
| 502 | S2R-RUN-0506 | The backend SOAP response did not match the expected contract (contract drift). |
| 502 | S2R-VAL-0430 | The backend response failed validation against the configured OpenAPI schema. |
| 502 | S2R-VAL-0431 | A field in the backend response failed validation against a configured regex pattern. |
| 503 | S2R-RUN-0503 | The backend service is unavailable (no active/healthy backends configured). |
| 503 | S2R-RUN-0529 | The circuit breaker to the backend service is open. |
| 504 | S2R-RUN-0424 | The backend service did not respond within the configured timeout. |
When a backend returns a SOAP Fault, the level of detail included in the client-facing error response is controlled by the faultDetailExposureMode:
safe (default): Only the faultCode is exposed. All other fields, which may contain sensitive backend information like stack traces or hostnames, are scrubbed.full: The entire parsed fault structure is passed through to the client.The full, unscrubbed fault is always available to operators in the transaction logs.
| Endpoint | Method(s) | Description |
|---|---|---|
/health/live | GET | Liveness probe. Always returns {"status": "UP"}. |
/health/ready | GET | Readiness probe. Checks database connectivity and license status. Returns 503 if the service is not ready to accept traffic. |
/{direction}/{environment}/** | GET, POST, PUT, PATCH, DELETE | Main data path for publish and consume directions. Also serves consume WSDLs. |
/gateway/{environment}/** | POST | Data path for gateway (SOAP passthrough) requests. |
/gateway/{environment}/** | GET | Serves WSDL contracts for gateway services. |
/{direction}/{env}/{svc}/{op}/async/{correlationId} | GET | Polls the status of an asynchronous operation. Requires X-S2R-Poll-Token header. |
/_s2r/callback/{env}/{svc}/{op} | POST | The endpoint for backend services to post results for asynchronous operations. |
| Header | Direction(s) | Usage |
|---|---|---|
X-Correlation-Id | All | A unique ID for tracing a request. If not provided by the client, one is generated. |
X-Debug-Enabled | publish | Set to true to enable debug-level logging for a request, overriding the route's setting. |
Content-Type | All | Specifies the media type of the request body (e.g., application/json, text/xml). |
SOAPAction | consume | Used to help resolve the specific operation for SOAP 1.1 requests. |
X-S2R-Poll-Token | publish (async) | Required on async poll requests to authenticate the poller. |
X-S2R-Callback-Secret | publish (async) | Used by the backend to authenticate itself when posting to the callback endpoint. |
EnforcementProbe.s2r_runtime_log table for auditing and troubleshooting.