Skip to content

Commit

Permalink
Decode URL-encoded headers in environment vars
Browse files Browse the repository at this point in the history
The [opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables) wants `OTEL_EXPORTER_OTLP_HEADERS` to conform to the [Baggage HTTP Header Format](https://github.com/w3c/baggage/blob/main/baggage/HTTP_HEADER_FORMAT.md).

To effectively use the headers from `OTEL_EXPORTER_OTLP_HEADERS` for
things like authentication (a common use case) the values need to be
decoded.

Given a header like this:

```
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic base64"
```

The code prior to this commit would reject the header for containing
whitespace mid-value.

If the header is modified to this:

```
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic%20base64"
```

The code prior to this commit would send the header as `Authorization:
Basic%20base64`, which will be rejected upstream.

This change applies `urllib.parse.unquote` to header **names** and
**values**, based on precedent set by the following libraries:

- [opentelemetry-go](https://github.com/open-telemetry/opentelemetry-go)
- [opentelemetry-js](https://github.com/open-telemetry/opentelemetry-js)
- [opentelemetry-ruby](https://github.com/open-telemetry/opentelemetry-ruby)
  • Loading branch information
mattoberle committed Dec 7, 2021
1 parent 8bbaf76 commit 85a1288
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
5 changes: 3 additions & 2 deletions opentelemetry-api/src/opentelemetry/util/re.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import logging
from re import compile, split
from typing import Mapping
from urllib.parse import unquote

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -51,8 +52,8 @@ def parse_headers(s: str) -> Mapping[str, str]:
continue
# value may contain any number of `=`
name, value = match.string.split("=", 1)
name = name.strip().lower()
value = value.strip()
name = unquote(name.strip()).lower()
value = unquote(value.strip())
headers[name] = value

return headers
5 changes: 5 additions & 0 deletions opentelemetry-api/tests/util/test_re.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ def test_parse_headers(self):
# different header values
("name=", [("name", "")], False),
("name===value=", [("name", "==value=")], False),
# url-encoded headers
("key=value%20with%20space", [("key", "value with space")], False),
("key%21=value", [("key!", "value")], False),
# header name case normalization
("Key=Value", [("key", "Value")], False),
# mix of valid and invalid headers
(
"name1=value1,invalidName, name2 = value2 , name3=value3==",
Expand Down

0 comments on commit 85a1288

Please sign in to comment.