Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static OkHttpClient createClient() {
.readTimeout(getReadTimeout())
.writeTimeout(getWriteTimeout())
.addInterceptor(LOGGING_INTERCEPTOR)
.addInterceptor(new TraceHeadersInterceptor())
.cache(getCache())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2026
* United States Army Corps of Engineers - Hydrologic Engineering Center (USACE/HEC)
* All Rights Reserved. USACE PROPRIETARY/CONFIDENTIAL.
* Source may not be released without written approval from HEC
*/

package mil.army.usace.hec.cwms.http.client;

import java.io.IOException;
import java.util.UUID;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

final class TraceHeadersInterceptor implements Interceptor {

private static final String TRACE_PARENT_HEADER = "traceparent";
private static final String TRACE_ID_HEADER = "X-Trace-Id";

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();

String traceId = generateTraceId();
String traceParent = createTraceParent(traceId);

Request tracedRequest = request.newBuilder()
.header(TRACE_ID_HEADER, traceId)
.header(TRACE_PARENT_HEADER, traceParent)
.build();

return chain.proceed(tracedRequest);
}

private static String generateTraceId() {
return UUID.randomUUID().toString().toLowerCase();
}

private static String createTraceParent(String traceId) {
String traceIdHex = traceId.replace("-", "");
String spanId = UUID.randomUUID().toString().replace("-", "").substring(0, 16).toLowerCase();
return "00-" + traceIdHex + "-" + spanId + "-01";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2026
* United States Army Corps of Engineers - Hydrologic Engineering Center (USACE/HEC)
* All Rights Reserved. USACE PROPRIETARY/CONFIDENTIAL.
* Source may not be released without written approval from HEC
*/

package mil.army.usace.hec.cwms.http.client;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.util.regex.Pattern;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.Test;

final class TraceHeadersInterceptorTest {

private static final Pattern TRACE_ID_PATTERN =
Pattern.compile("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}", Pattern.CASE_INSENSITIVE);


@Test
void testCookiesNotLogged() throws IOException, InterruptedException {
try(MockWebServer mockWebServer = new MockWebServer()) {
MockResponse mockResponse = new MockResponse()
.setBody("test")
.setResponseCode(200);
mockWebServer.enqueue(mockResponse);
mockWebServer.start();

Request request = new Request.Builder()
.url(mockWebServer.url("/test"))
.build();
try (Response response = OkHttpClientInstance.getInstance().newCall(request).execute()) {
assertTrue(response.isSuccessful());
}

okhttp3.mockwebserver.RecordedRequest recordedRequest = mockWebServer.takeRequest();
String traceId = recordedRequest.getHeader("X-Trace-Id");
String traceParent = recordedRequest.getHeader("traceparent");

assertTrue(traceId != null && TRACE_ID_PATTERN.matcher(traceId).matches(),
"X-Trace-Id should be a UUID-like value");
assertTrue(traceParent != null && traceParent.matches(
"00-[a-f0-9]{32}-[a-f0-9]{16}-[a-f0-9]{2}"),
"traceparent should follow W3C format: https://www.w3.org/TR/trace-context/#traceparent-header");
assertTrue(traceParent.startsWith("00-"));
assertEquals(4, traceParent.split("-").length);
}
}
}
Loading