Spring Boot starter that helps applications proxy HTTP calls while preserving Woody tracing context and OpenTelemetry spans.
- Servlet filter that restores incoming Woody trace headers and propagates them downstream.
- Response handler that maps Woody errors to HTTP responses and enriches outgoing headers.
- Optional OTLP exporter configuration (enabled by default via
otel.*properties).
Add the dependency to your project:
<dependency>
<groupId>dev.vality</groupId>
<artifactId>woody-http-bridge</artifactId>
<version>${woody-http-bridge.version}</version>
</dependency>No additional setup is required: the auto-configuration registers the tracing filter and response handler in servlet environments.
Configure endpoints that should participate in Woody tracing via woody-http-bridge.tracing:
woody-http-bridge:
tracing:
endpoints:
- path: /api
port: 8080Key options:
woody-http-bridge.enabledwoody-http-bridge.tracing.endpoints[0].propagate-errors— whentrue, exceptions bubble up; otherwise they are converted to Woody error responses.woody-http-bridge.tracing.endpoints[0].default-cipher-token— optional fallback token (Base64 URL-encoded) used when no token is present in request forCIPHER_TOKEN_EXPERIMENTALmode.woody-http-bridge.tracing.endpoints[0].token-ttl— optional TTL in minutes for validating decrypted tokens.
| Mode | Description |
|---|---|
OFF |
Ignores any incoming tracing hints and starts a new trace context for each request. |
WOODY_OR_X_WOODY |
Reads Woody headers using either the internal Woody-* or external X-Woody-* prefixes without token processing. |
CIPHER_TOKEN_EXPERIMENTAL |
Locates an encrypted token via CipherTokenExtractor, decrypts it with TokenCipher, and restores the trace from the resulting TokenPayload. Be aware of transport limits (e.g., some systems cap URLs at 255 characters) when embedding encrypted tokens. |
VAULT_TOKEN_EXPERIMENTAL |
Resolves a token key using VaultTokenKeyExtractor, loads a TokenPayload from SecretService/Vault, and applies it to the request. High-traffic services with long token retention can generate substantial Vault load. |
| Mode | Description |
|---|---|
OFF |
Suppresses outgoing Woody headers. |
WOODY |
Emits canonical Woody-* headers on the response. |
X_WOODY |
Emits external-facing X-Woody-* headers for compatibility with edge components. |
HTTP |
Emits minimal traceparent and tracestate headers understood by OpenTelemetry tools. |
CIPHER_TOKEN_EXPERIMENTAL— filter extracts an encrypted token from the request (viaCipherTokenExtractor), decrypts it withTokenCipher, validates TTL, restorestraceparent/tracestate, and runs the request inside the recovered context. BeanCipherTokenExtractorcan be overridden; default implementation reads the last path segment. The cipher secret is cached for one minute between Vault lookups; if you rotate it more often, refresh the application or provide your ownSecretServicebean. Consider token size limits if the token is transported in a URL or storage-constrained medium.VAULT_TOKEN_EXPERIMENTAL— filter extracts a token key (viaVaultTokenKeyExtractor), loads a plainTokenPayloadfromSecretService(backed by Vault), validates TTL, and restores tracing. BeanVaultTokenKeyExtractorcan be overridden; default implementation reads the last path segment. Heavy traffic or long-lived tokens may increase Vault storage and request pressure.SecretServicekeeps Vault tokens in structured form (trace ids, span ids,traceparent,tracestate) and caches the cipher secret key for encrypted mode.
Both token modes delegate the lookup to Spring beans so that consumers decide where the token or token key lives. Provide your own CipherTokenExtractor or VaultTokenKeyExtractor bean to switch to a different transport channel.
Example implementations
@Component
class HeaderTokenExtractor implements CipherTokenExtractor {
@Override
public String extractToken(HttpServletRequest request) {
return request.getHeader("X-Cipher-Token");
}
}@Component
class QueryTokenKeyExtractor implements VaultTokenKeyExtractor {
@Override
public String extractTokenKey(HttpServletRequest request) {
return request.getParameter("vaultKey");
}
}@Component
class BodyTokenExtractor implements CipherTokenExtractor {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public String extractToken(HttpServletRequest request) {
try {
var node = mapper.readTree(request.getInputStream());
return node.path("cipherToken").asText(null);
} catch (IOException ex) {
throw new IllegalStateException("Unable to read cipher token", ex);
}
}
}Any of these beans automatically override the defaults registered by the starter.
To change how an inbound token is located (e.g., URL segment vs. header vs. body), provide your own Spring beans implementing CipherTokenExtractor or VaultTokenKeyExtractor which will replace the defaults automatically.
For CIPHER_TOKEN_EXPERIMENTAL it is common to embed the encrypted token directly into a callback URL. The following Java example mirrors the Kotlin helper shown in the comments and appends the encrypted token as the last path segment:
@Service
@RequiredArgsConstructor
public class CallbackUrlManager {
private final AdapterCustomProperties properties;
private final TokenCipher tokenCipher;
private final SecretService secretService;
private final int restPort;
private final String restEndpoint;
public String initCallbackUrl(TokenPayload payload) {
return buildUrl(properties.getPathCallbackUrl(), encrypt(payload));
}
public String initRedirectUrl(TokenPayload payload) {
return buildUrl(properties.getPathRedirectUrl(), encrypt(payload));
}
private String encrypt(TokenPayload payload) {
String secret = secretService.getCipherTokenSecretKey(restPort, restEndpoint);
return tokenCipher.encrypt(payload, secret);
}
private String buildUrl(String path, String token) {
return UriComponentsBuilder
.fromUriString(properties.getCallbackUrl())
.path(path)
.pathSegment(token)
.toUriString();
}
}Vault integration is optional. To bootstrap the provided Vault support enable it explicitly:
vault:
enabled: true
uri: https://vault.empayre.com:443
token: "xxx"When disabled (default), the application must provide its own VaultSecretService/SecretService beans if VAULT_TOKEN mode is required.
The starter exposes an OTLP exporter that can be controlled with otel.* properties:
otel:
enabled: true
resource: http://collector:4318/v1/traces
timeout: 60000Disable telemetry entirely by setting otel.enabled=false.
Apache 2.0 — see LICENSE.