Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
15 changes: 8 additions & 7 deletions sentry/src/main/java/io/sentry/SentryTraceHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public final class SentryTraceHeader {
private final @NotNull SpanId spanId;
private final @Nullable Boolean sampled;

// Use numbered capture groups for Android API level < 26 compatibility
private static final Pattern SENTRY_TRACEPARENT_HEADER_REGEX =
Pattern.compile(
"^[ \\t]*(?<traceId>[0-9a-f]{32})-(?<spanId>[0-9a-f]{16})(?<sampled>-[01])?[ \\t]*$",
Pattern.CASE_INSENSITIVE);
"^[ \\t]*([0-9a-f]{32})-([0-9a-f]{16})(-[01])?[ \\t]*$", Pattern.CASE_INSENSITIVE);

public SentryTraceHeader(
final @NotNull SentryId traceId,
Expand All @@ -33,14 +33,15 @@ public SentryTraceHeader(final @NotNull String value) throws InvalidSentryTraceH
Matcher matcher = SENTRY_TRACEPARENT_HEADER_REGEX.matcher(value);
boolean matchesExist = matcher.matches();

if (!matchesExist || matcher.group("traceId") == null || matcher.group("spanId") == null) {
if (!matchesExist) {
throw new InvalidSentryTraceHeaderException(value);
}

this.traceId = new SentryId(matcher.group("traceId"));
this.spanId = new SpanId(matcher.group("spanId"));
this.sampled =
matcher.group("sampled") == null ? null : "1".equals(matcher.group("sampled").substring(1));
this.traceId = new SentryId(matcher.group(1));
this.spanId = new SpanId(matcher.group(2));

String sampled = matcher.group(3);
this.sampled = sampled == null ? null : "1".equals(sampled.substring(1));
}

public @NotNull String getName() {
Expand Down
20 changes: 20 additions & 0 deletions sentry/src/test/java/io/sentry/SentryTraceHeaderTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ class SentryTraceHeaderTest {
assertNull(header.isSampled)
}

@Test
fun `handles header without sampling decision and leading whitespace`() {
val sentryId = SentryId()
val spanId = SpanId()
val header = SentryTraceHeader(" \t $sentryId-$spanId")
assertEquals(sentryId, header.traceId)
assertEquals(spanId, header.spanId)
assertNull(header.isSampled)
}

@Test
fun `handles header without sampling decision and trailing whitespace`() {
val sentryId = SentryId()
val spanId = SpanId()
val header = SentryTraceHeader("$sentryId-$spanId \t ")
assertEquals(sentryId, header.traceId)
assertEquals(spanId, header.spanId)
assertNull(header.isSampled)
}

@Test
fun `when sampling decision is not made, getValue returns header with traceId and spanId`() {
val sentryId = SentryId()
Expand Down
Loading