Skip to content

Commit cc38c52

Browse files
authored
Add header to indicate user tracking suppression (#89)
1 parent 3e82918 commit cc38c52

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContext.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
44
import static java.util.Objects.requireNonNull;
55
import static org.hypertrace.core.grpcutils.context.RequestContextConstants.CACHE_MEANINGFUL_HEADERS;
6+
import static org.hypertrace.core.grpcutils.context.RequestContextConstants.SUPPRESS_USER_TRACKING_HEADER_KEY;
67
import static org.hypertrace.core.grpcutils.context.RequestContextConstants.TENANT_ID_HEADER_KEY;
78

89
import com.google.common.collect.ListMultimap;
@@ -120,6 +121,21 @@ public Optional<String> getRequestId() {
120121
return this.getHeaderValue(RequestContextConstants.REQUEST_ID_HEADER_KEY);
121122
}
122123

124+
public boolean isUserTrackingSuppressed() {
125+
return this.getHeaderValue(SUPPRESS_USER_TRACKING_HEADER_KEY)
126+
.map(Boolean::parseBoolean)
127+
.orElse(false);
128+
}
129+
130+
public RequestContext withUserTrackingSuppressed(boolean suppressed) {
131+
this.removeHeader(SUPPRESS_USER_TRACKING_HEADER_KEY);
132+
return this.put(SUPPRESS_USER_TRACKING_HEADER_KEY, String.valueOf(suppressed));
133+
}
134+
135+
public RequestContext withUserTrackingSuppressed() {
136+
return this.withUserTrackingSuppressed(true);
137+
}
138+
123139
private Optional<Jwt> getJwt() {
124140
return this.getHeaderValue(RequestContextConstants.AUTHORIZATION_HEADER)
125141
.flatMap(JWT_PARSER::fromAuthHeader);

grpc-context-utils/src/main/java/org/hypertrace/core/grpcutils/context/RequestContextConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class RequestContextConstants {
1313
public static final String TENANT_ID_HEADER_KEY = "x-tenant-id";
1414
public static final String REQUEST_ID_HEADER_KEY = "request-id";
1515
public static final String CONTEXT_ID_HEADER_KEY = "context-id";
16+
public static final String SUPPRESS_USER_TRACKING_HEADER_KEY = "x-suppress-user-tracking";
1617

1718
public static final Metadata.Key<String> TENANT_ID_METADATA_KEY =
1819
Metadata.Key.of(TENANT_ID_HEADER_KEY, ASCII_STRING_MARSHALLER);
@@ -24,6 +25,7 @@ public class RequestContextConstants {
2425
Set.of(
2526
TENANT_ID_HEADER_KEY,
2627
CONTEXT_ID_HEADER_KEY,
28+
SUPPRESS_USER_TRACKING_HEADER_KEY,
2729
"X-B3-",
2830
"grpc-trace-bin",
2931
"traceparent",

grpc-context-utils/src/test/java/org/hypertrace/core/grpcutils/context/RequestContextTest.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
44
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertFalse;
56
import static org.junit.jupiter.api.Assertions.assertNotEquals;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
68

79
import com.google.common.collect.ImmutableList;
810
import io.grpc.Metadata;
@@ -251,4 +253,86 @@ void backwardsCompatibilityForAdd() {
251253
assertEquals(Optional.of("f-v2"), requestContext.getHeaderValue("first"));
252254
assertEquals(List.of("f-v2"), requestContext.getAllHeaderValues("first"));
253255
}
256+
257+
@Test
258+
void testUserTrackingSuppressedDefault() {
259+
RequestContext requestContext = new RequestContext();
260+
assertFalse(requestContext.isUserTrackingSuppressed());
261+
}
262+
263+
@Test
264+
void testUserTrackingSuppressedWithTrueValue() {
265+
RequestContext requestContext =
266+
new RequestContext().put(RequestContextConstants.SUPPRESS_USER_TRACKING_HEADER_KEY, "true");
267+
assertTrue(requestContext.isUserTrackingSuppressed());
268+
}
269+
270+
@Test
271+
void testUserTrackingSuppressedWithFalseValue() {
272+
RequestContext requestContext =
273+
new RequestContext()
274+
.put(RequestContextConstants.SUPPRESS_USER_TRACKING_HEADER_KEY, "false");
275+
assertFalse(requestContext.isUserTrackingSuppressed());
276+
}
277+
278+
@Test
279+
void testWithUserTrackingSuppressedBoolean() {
280+
RequestContext originalContext1 = new RequestContext();
281+
RequestContext suppressedContext = originalContext1.withUserTrackingSuppressed(true);
282+
assertTrue(suppressedContext.isUserTrackingSuppressed());
283+
284+
RequestContext originalContext2 = new RequestContext();
285+
RequestContext unsuppressedContext = originalContext2.withUserTrackingSuppressed(false);
286+
assertFalse(unsuppressedContext.isUserTrackingSuppressed());
287+
}
288+
289+
@Test
290+
void testWithUserTrackingSuppressedDefault() {
291+
RequestContext originalContext = new RequestContext();
292+
293+
RequestContext suppressedContext = originalContext.withUserTrackingSuppressed();
294+
assertTrue(suppressedContext.isUserTrackingSuppressed());
295+
}
296+
297+
@Test
298+
void testWithUserTrackingSuppressedPreservesOtherHeaders() {
299+
RequestContext originalContext =
300+
new RequestContext()
301+
.put(RequestContextConstants.TENANT_ID_HEADER_KEY, "tenant-123")
302+
.put("other-header", "other-value");
303+
304+
RequestContext suppressedContext = originalContext.withUserTrackingSuppressed();
305+
306+
assertTrue(suppressedContext.isUserTrackingSuppressed());
307+
assertEquals(Optional.of("tenant-123"), suppressedContext.getTenantId());
308+
assertEquals(Optional.of("other-value"), suppressedContext.getHeaderValue("other-header"));
309+
}
310+
311+
@Test
312+
void testWithUserTrackingSuppressedOverridesExisting() {
313+
RequestContext originalContext =
314+
new RequestContext()
315+
.put(RequestContextConstants.SUPPRESS_USER_TRACKING_HEADER_KEY, "false");
316+
317+
assertFalse(originalContext.isUserTrackingSuppressed());
318+
319+
RequestContext suppressedContext = originalContext.withUserTrackingSuppressed();
320+
assertTrue(suppressedContext.isUserTrackingSuppressed());
321+
}
322+
323+
@Test
324+
void testUserTrackingSuppressedHeaderPropagation() {
325+
Metadata metadata = new Metadata();
326+
metadata.put(
327+
Metadata.Key.of(
328+
RequestContextConstants.SUPPRESS_USER_TRACKING_HEADER_KEY,
329+
Metadata.ASCII_STRING_MARSHALLER),
330+
"true");
331+
metadata.put(RequestContextConstants.TENANT_ID_METADATA_KEY, "test-tenant");
332+
333+
RequestContext requestContext = RequestContext.fromMetadata(metadata);
334+
335+
assertTrue(requestContext.isUserTrackingSuppressed());
336+
assertEquals(Optional.of("test-tenant"), requestContext.getTenantId());
337+
}
254338
}

0 commit comments

Comments
 (0)