From 719ff4096f881621b010e0cf6d8f79138aa1225c Mon Sep 17 00:00:00 2001 From: Lester Haynes Date: Tue, 5 Dec 2023 16:28:55 -0800 Subject: [PATCH] Add support for commas in values for exporter.otlp.headers --- .../spi/internal/DefaultConfigProperties.java | 16 +++++++++++++- .../spi/internal/ConfigPropertiesTest.java | 21 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java index b8673993fe3..0aa7e112d9b 100644 --- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java @@ -181,7 +181,21 @@ public List getList(String name) { if (value == null) { return Collections.emptyList(); } - return filterBlanksAndNulls(value.split(",")); + + // Support list members containing commas per RFC9110 5.5 suggestion + String[] listMembers; + // check if list members are double-quoted + if (value.startsWith("\"") && value.endsWith("\"")) { + // remove first and last quote and split on '","' + value = value.substring(1, value.length() - 1); + listMembers = value.split("\"\\s?,\\s?\""); + } else if (value.contains(",") && value.contains("\"")) { + throw new ConfigurationException("Invalid list property: " + name + "=" + config.get(name)); + } else { + listMembers = value.split(","); + } + + return filterBlanksAndNulls(listMembers); } /** diff --git a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java index e0fe198dc9e..b03b9cd8653 100644 --- a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java +++ b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java @@ -34,6 +34,9 @@ void allValid() { assertThat(config.getList("test.list")).containsExactly("cat", "dog", "bear"); assertThat(config.getMap("test.map")) .containsExactly(entry("cat", "meow"), entry("dog", "bark"), entry("bear", "growl")); + assertThat(config.getMap("test.map.commas")) + .containsExactly( + entry("cat", "meow,hiss"), entry("dog", "bark,growl"), entry("bear", "growl,roar")); assertThat(config.getDuration("test.duration")).isEqualTo(Duration.ofSeconds(1)); } @@ -49,6 +52,9 @@ void allValidUsingHyphens() { assertThat(config.getList("test-list")).containsExactly("cat", "dog", "bear"); assertThat(config.getMap("test-map")) .containsExactly(entry("cat", "meow"), entry("dog", "bark"), entry("bear", "growl")); + assertThat(config.getMap("test-map-commas")) + .containsExactly( + entry("cat", "meow,hiss"), entry("dog", "bark,growl"), entry("bear", "growl,roar")); assertThat(config.getDuration("test-duration")).isEqualTo(Duration.ofSeconds(1)); } @@ -61,6 +67,7 @@ void allMissing() { assertThat(config.getDouble("test.double")).isNull(); assertThat(config.getList("test.list")).isEmpty(); assertThat(config.getMap("test.map")).isEmpty(); + assertThat(config.getMap("test.map.commas")).isEmpty(); assertThat(config.getDuration("test.duration")).isNull(); } @@ -73,6 +80,7 @@ void allEmpty() { properties.put("test.double", ""); properties.put("test.list", ""); properties.put("test.map", ""); + properties.put("test.map.commas", ""); properties.put("test.duration", ""); ConfigProperties config = DefaultConfigProperties.createFromMap(properties); @@ -82,6 +90,7 @@ void allEmpty() { assertThat(config.getDouble("test.double")).isNull(); assertThat(config.getList("test.list")).isEmpty(); assertThat(config.getMap("test.map")).isEmpty(); + assertThat(config.getMap("test.map.commas")).isEmpty(); assertThat(config.getDuration("test.duration")).isNull(); } @@ -169,6 +178,17 @@ void invalidMap() { .hasMessage("Invalid map property: map=a=1,=b"); } + @Test + void invalidList() { + DefaultConfigProperties config = + DefaultConfigProperties.createFromMap( + Collections.singletonMap( + "invalid", "\"cat=meow,hiss\",\"dog=bark,growl\", bear=growl")); + assertThatThrownBy(() -> config.getList("invalid")) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Invalid list property"); + } + @Test void invalidDuration() { assertThatThrownBy( @@ -277,6 +297,7 @@ private static Map makeTestProps() { properties.put("test.list", "cat,dog,bear"); properties.put("test.map", "cat=meow,dog=bark,bear=growl,bird="); properties.put("test.duration", "1s"); + properties.put("test.map.commas", "\"cat=meow,hiss\",\"dog=bark,growl\", \"bear=growl,roar\""); return properties; } }