You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-07-17 01:12:45 +02:00
Use url.PathUnescape rather than url.QueryUnescape when parsing OTLP headers and resource attributes env vars (#4698) (#4699)
This commit is contained in:
@ -59,7 +59,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix improper parsing of characters such us `+`, `\` by `Parse` in `go.opentelemetry.io/otel/baggage` as they were rendered as a whitespace. (#4667)
|
||||
- Fix improper parsing of characters such us `+`, `/` by `Parse` in `go.opentelemetry.io/otel/baggage` as they were rendered as a whitespace. (#4667)
|
||||
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_RESOURCE_ATTRIBUTES` in `go.opentelemetry.io/otel/sdk/resource` as they were rendered as a whitespace. (#4699)
|
||||
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` as they were rendered as a whitespace. (#4699)
|
||||
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` as they were rendered as a whitespace. (#4699)
|
||||
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TRACES_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracegrpc` as they were rendered as a whitespace. (#4699)
|
||||
- Fix improper parsing of characters such us `+`, `/` passed via `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TRACES_HEADERS` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlptracehttp` as they were rendered as a whitespace. (#4699)
|
||||
- In `go.opentelemetry.op/otel/exporters/prometheus`, the exporter no longer `Collect`s metrics after `Shutdown` is invoked. (#4648)
|
||||
- Fix documentation for `WithCompressor` in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#4695)
|
||||
- Fix documentation for `WithCompressor` in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4695)
|
||||
|
@ -174,13 +174,13 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
|
@ -427,7 +427,12 @@ func TestStringToHeader(t *testing.T) {
|
||||
want: map[string]string{"userId": "alice"},
|
||||
},
|
||||
{
|
||||
name: "multiples headers encoded",
|
||||
name: "simple header conforms to RFC 3986 spec",
|
||||
value: " userId = alice+test ",
|
||||
want: map[string]string{"userId": "alice+test"},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded",
|
||||
value: "userId=alice,serverNode=DF%3A28,isProduction=false",
|
||||
want: map[string]string{
|
||||
"userId": "alice",
|
||||
@ -435,6 +440,16 @@ func TestStringToHeader(t *testing.T) {
|
||||
"isProduction": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded per RFC 3986 spec",
|
||||
value: "userId=alice+test,serverNode=DF%3A28,isProduction=false,namespace=localhost/test",
|
||||
want: map[string]string{
|
||||
"userId": "alice+test",
|
||||
"serverNode": "DF:28",
|
||||
"isProduction": "false",
|
||||
"namespace": "localhost/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid headers format",
|
||||
value: "userId:alice",
|
||||
|
@ -174,13 +174,13 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
|
@ -427,7 +427,12 @@ func TestStringToHeader(t *testing.T) {
|
||||
want: map[string]string{"userId": "alice"},
|
||||
},
|
||||
{
|
||||
name: "multiples headers encoded",
|
||||
name: "simple header conforms to RFC 3986 spec",
|
||||
value: " userId = alice+test ",
|
||||
want: map[string]string{"userId": "alice+test"},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded",
|
||||
value: "userId=alice,serverNode=DF%3A28,isProduction=false",
|
||||
want: map[string]string{
|
||||
"userId": "alice",
|
||||
@ -435,6 +440,16 @@ func TestStringToHeader(t *testing.T) {
|
||||
"isProduction": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded per RFC 3986 spec",
|
||||
value: "userId=alice+test,serverNode=DF%3A28,isProduction=false,namespace=localhost/test",
|
||||
want: map[string]string{
|
||||
"userId": "alice+test",
|
||||
"serverNode": "DF:28",
|
||||
"isProduction": "false",
|
||||
"namespace": "localhost/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid headers format",
|
||||
value: "userId:alice",
|
||||
|
@ -174,13 +174,13 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
|
@ -427,7 +427,12 @@ func TestStringToHeader(t *testing.T) {
|
||||
want: map[string]string{"userId": "alice"},
|
||||
},
|
||||
{
|
||||
name: "multiples headers encoded",
|
||||
name: "simple header conforms to RFC 3986 spec",
|
||||
value: " userId = alice+test ",
|
||||
want: map[string]string{"userId": "alice+test"},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded",
|
||||
value: "userId=alice,serverNode=DF%3A28,isProduction=false",
|
||||
want: map[string]string{
|
||||
"userId": "alice",
|
||||
@ -435,6 +440,16 @@ func TestStringToHeader(t *testing.T) {
|
||||
"isProduction": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded per RFC 3986 spec",
|
||||
value: "userId=alice+test,serverNode=DF%3A28,isProduction=false,namespace=localhost/test",
|
||||
want: map[string]string{
|
||||
"userId": "alice+test",
|
||||
"serverNode": "DF:28",
|
||||
"isProduction": "false",
|
||||
"namespace": "localhost/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid headers format",
|
||||
value: "userId:alice",
|
||||
|
@ -174,13 +174,13 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
|
@ -427,7 +427,12 @@ func TestStringToHeader(t *testing.T) {
|
||||
want: map[string]string{"userId": "alice"},
|
||||
},
|
||||
{
|
||||
name: "multiples headers encoded",
|
||||
name: "simple header conforms to RFC 3986 spec",
|
||||
value: " userId = alice+test ",
|
||||
want: map[string]string{"userId": "alice+test"},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded",
|
||||
value: "userId=alice,serverNode=DF%3A28,isProduction=false",
|
||||
want: map[string]string{
|
||||
"userId": "alice",
|
||||
@ -435,6 +440,16 @@ func TestStringToHeader(t *testing.T) {
|
||||
"isProduction": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded per RFC 3986 spec",
|
||||
value: "userId=alice+test,serverNode=DF%3A28,isProduction=false,namespace=localhost/test",
|
||||
want: map[string]string{
|
||||
"userId": "alice+test",
|
||||
"serverNode": "DF:28",
|
||||
"isProduction": "false",
|
||||
"namespace": "localhost/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid headers format",
|
||||
value: "userId:alice",
|
||||
|
@ -174,13 +174,13 @@ func stringToHeader(value string) map[string]string {
|
||||
global.Error(errors.New("missing '="), "parse headers", "input", header)
|
||||
continue
|
||||
}
|
||||
name, err := url.QueryUnescape(n)
|
||||
name, err := url.PathUnescape(n)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header key", "key", n)
|
||||
continue
|
||||
}
|
||||
trimmedName := strings.TrimSpace(name)
|
||||
value, err := url.QueryUnescape(v)
|
||||
value, err := url.PathUnescape(v)
|
||||
if err != nil {
|
||||
global.Error(err, "escape header value", "value", v)
|
||||
continue
|
||||
|
@ -427,7 +427,12 @@ func TestStringToHeader(t *testing.T) {
|
||||
want: map[string]string{"userId": "alice"},
|
||||
},
|
||||
{
|
||||
name: "multiples headers encoded",
|
||||
name: "simple header conforms to RFC 3986 spec",
|
||||
value: " userId = alice+test ",
|
||||
want: map[string]string{"userId": "alice+test"},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded",
|
||||
value: "userId=alice,serverNode=DF%3A28,isProduction=false",
|
||||
want: map[string]string{
|
||||
"userId": "alice",
|
||||
@ -435,6 +440,16 @@ func TestStringToHeader(t *testing.T) {
|
||||
"isProduction": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple headers encoded per RFC 3986 spec",
|
||||
value: "userId=alice+test,serverNode=DF%3A28,isProduction=false,namespace=localhost/test",
|
||||
want: map[string]string{
|
||||
"userId": "alice+test",
|
||||
"serverNode": "DF:28",
|
||||
"isProduction": "false",
|
||||
"namespace": "localhost/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid headers format",
|
||||
value: "userId:alice",
|
||||
|
@ -89,7 +89,7 @@ func constructOTResources(s string) (*Resource, error) {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(k)
|
||||
val, err := url.QueryUnescape(strings.TrimSpace(v))
|
||||
val, err := url.PathUnescape(strings.TrimSpace(v))
|
||||
if err != nil {
|
||||
// Retain original value if decoding fails, otherwise it will be
|
||||
// an empty string.
|
||||
|
@ -40,6 +40,19 @@ func TestDetectOnePair(t *testing.T) {
|
||||
assert.Equal(t, NewSchemaless(attribute.String("key", "value")), res)
|
||||
}
|
||||
|
||||
func TestDetectURIEncodingOnePair(t *testing.T) {
|
||||
store, err := ottest.SetEnvVariables(map[string]string{
|
||||
resourceAttrKey: "key=x+y+z?q=123",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer func() { require.NoError(t, store.Restore()) }()
|
||||
|
||||
detector := &fromEnv{}
|
||||
res, err := detector.Detect(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, NewSchemaless(attribute.String("key", "x+y+z?q=123")), res)
|
||||
}
|
||||
|
||||
func TestDetectMultiPairs(t *testing.T) {
|
||||
store, err := ottest.SetEnvVariables(map[string]string{
|
||||
"x": "1",
|
||||
@ -60,6 +73,23 @@ func TestDetectMultiPairs(t *testing.T) {
|
||||
), res)
|
||||
}
|
||||
|
||||
func TestDetectURIEncodingMultiPairs(t *testing.T) {
|
||||
store, err := ottest.SetEnvVariables(map[string]string{
|
||||
"x": "1",
|
||||
resourceAttrKey: "key=x+y+z,namespace=localhost/test&verify",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer func() { require.NoError(t, store.Restore()) }()
|
||||
|
||||
detector := &fromEnv{}
|
||||
res, err := detector.Detect(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, NewSchemaless(
|
||||
attribute.String("key", "x+y+z"),
|
||||
attribute.String("namespace", "localhost/test&verify"),
|
||||
), res)
|
||||
}
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
store, err := ottest.SetEnvVariables(map[string]string{
|
||||
resourceAttrKey: " ",
|
||||
|
Reference in New Issue
Block a user