From 8b5d88a1429551a66c9b68013f335ba651f45575 Mon Sep 17 00:00:00 2001 From: dahyvuun Date: Wed, 10 Jun 2026 16:47:29 +0200 Subject: [PATCH 1/2] Fix W3CBaggagePropagator to allow empty baggage values per W3C spec --- .../api/baggage/propagation/Element.java | 13 ++++++++++++- .../propagation/W3CBaggagePropagatorTest.java | 7 +++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java index f6bdaec9eb3..e8b1379c3f1 100644 --- a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java +++ b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java @@ -31,6 +31,8 @@ class Element { } private final BitSet excluded; + private boolean allowEmpty; + private boolean seenWhitespace; private boolean leadingSpace; private boolean readingValue; @@ -44,7 +46,9 @@ static Element createKeyElement() { } static Element createValueElement() { - return new Element(EXCLUDED_VALUE_CHARS); + Element element = new Element(EXCLUDED_VALUE_CHARS); + element.allowEmpty = true; + return element; } /** @@ -54,6 +58,7 @@ static Element createValueElement() { */ private Element(BitSet excluded) { this.excluded = excluded; + this.allowEmpty = false; reset(0); } @@ -68,6 +73,7 @@ void reset(int start) { readingValue = false; trailingSpace = false; value = null; + seenWhitespace = false; } boolean tryTerminating(int index, String header) { @@ -77,6 +83,9 @@ boolean tryTerminating(int index, String header) { if (this.trailingSpace) { setValue(header); return true; + } else if (allowEmpty && !seenWhitespace) { + this.value = ""; + return true; } else { // leading spaces - no content, invalid return false; @@ -110,6 +119,8 @@ private static boolean isWhitespace(char character) { private boolean tryNextWhitespace(int index) { if (readingValue) { markEnd(index); + } else { + seenWhitespace = true; } return true; } diff --git a/api/all/src/test/java/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagatorTest.java b/api/all/src/test/java/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagatorTest.java index 93f4e25f1a6..c030a258446 100644 --- a/api/all/src/test/java/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagatorTest.java +++ b/api/all/src/test/java/io/opentelemetry/api/baggage/propagation/W3CBaggagePropagatorTest.java @@ -208,7 +208,8 @@ void extract_value_empty() { Context result = propagator.extract(Context.root(), ImmutableMap.of("baggage", "key1="), getter); - assertThat(Baggage.fromContext(result)).isEqualTo(Baggage.empty()); + Baggage expectedBaggage = Baggage.builder().put("key1", "").build(); + assertThat(Baggage.fromContext(result)).isEqualTo(expectedBaggage); } @Test @@ -219,7 +220,9 @@ void extract_value_empty_withMetadata() { propagator.extract( Context.root(), ImmutableMap.of("baggage", "key1=;metakey=metaval"), getter); - assertThat(Baggage.fromContext(result)).isEqualTo(Baggage.empty()); + Baggage expectedBaggage = + Baggage.builder().put("key1", "", BaggageEntryMetadata.create("metakey=metaval")).build(); + assertThat(Baggage.fromContext(result)).isEqualTo(expectedBaggage); } @Test From 7c54f006fadf49e2fdee38d86d890415285b0478 Mon Sep 17 00:00:00 2001 From: dahyvuun Date: Thu, 11 Jun 2026 09:12:34 +0200 Subject: [PATCH 2/2] Make allowEmpty field final and refactor constructor --- .../api/baggage/propagation/Element.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java index e8b1379c3f1..cc1791e80f0 100644 --- a/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java +++ b/api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Element.java @@ -31,7 +31,7 @@ class Element { } private final BitSet excluded; - private boolean allowEmpty; + private final boolean allowEmpty; private boolean seenWhitespace; private boolean leadingSpace; @@ -42,13 +42,11 @@ class Element { @Nullable private String value; static Element createKeyElement() { - return new Element(EXCLUDED_KEY_CHARS); + return new Element(EXCLUDED_KEY_CHARS, /* allowEmpty= */ false); } static Element createValueElement() { - Element element = new Element(EXCLUDED_VALUE_CHARS); - element.allowEmpty = true; - return element; + return new Element(EXCLUDED_VALUE_CHARS, /* allowEmpty= */ true); } /** @@ -56,9 +54,9 @@ static Element createValueElement() { * * @param excluded characters that are not allowed for this type of an element */ - private Element(BitSet excluded) { + private Element(BitSet excluded, boolean allowEmpty) { this.excluded = excluded; - this.allowEmpty = false; + this.allowEmpty = allowEmpty; reset(0); }