Skip to content

Commit

Permalink
Support URL-encoded values for OTEL_EXPORTER_OTLP_HEADERS (open-tel…
Browse files Browse the repository at this point in the history
  • Loading branch information
pyohannes authored Mar 7, 2024
1 parent 14f7542 commit e5c2e25
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Increment the:

* [EXPORTER] Gzip compression support for OTLP/HTTP and OTLP/gRPC exporter
[#2530](https://github.com/open-telemetry/opentelemetry-cpp/pull/2530)
* [EXPORTER] Support URL-encoded values for `OTEL_EXPORTER_OTLP_HEADERS`
[#2579](https://github.com/open-telemetry/opentelemetry-cpp/pull/2579)

Important changes:

Expand Down
3 changes: 2 additions & 1 deletion exporters/otlp/src/otlp_grpc_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ std::unique_ptr<grpc::ClientContext> OtlpGrpcClient::MakeClientContext(

for (auto &header : options.metadata)
{
context->AddMetadata(header.first, header.second);
context->AddMetadata(header.first,
opentelemetry::ext::http::common::UrlDecoder::Decode(header.second));
}

return context;
Expand Down
3 changes: 2 additions & 1 deletion exporters/otlp/src/otlp_http_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,8 @@ OtlpHttpClient::createSession(

for (auto &header : options_.http_headers)
{
request->AddHeader(header.first, header.second);
request->AddHeader(header.first,
opentelemetry::ext::http::common::UrlDecoder::Decode(header.second));
}
request->SetUri(http_uri_);
request->SetSslOptions(options_.ssl_options);
Expand Down
44 changes: 44 additions & 0 deletions ext/include/opentelemetry/ext/http/common/url_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,50 @@ class UrlParser
}
};

class UrlDecoder
{
public:
static std::string Decode(const std::string &encoded)
{
std::string result;
result.reserve(encoded.size());

for (size_t pos = 0; pos < encoded.size(); pos++)
{
if (encoded[pos] == '%')
{

// Invalid input: less than two characters left after '%'
if (encoded.size() < pos + 3)
{
return encoded;
}

char hex[3] = {0};
hex[0] = encoded[++pos];
hex[1] = encoded[++pos];

char *endptr;
long value = strtol(hex, &endptr, 16);

// Invalid input: no valid hex characters after '%'
if (endptr != &hex[2])
{
return encoded;
}

result.push_back(static_cast<char>(value));
}
else
{
result.push_back(encoded[pos]);
}
}

return result;
}
};

} // namespace common

} // namespace http
Expand Down
18 changes: 18 additions & 0 deletions ext/test/http/url_parser_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,21 @@ TEST(UrlParserTests, BasicTests)
ASSERT_EQ(url.query_, url_properties["query"]);
}
}

TEST(UrlDecoderTests, BasicTests)
{
std::map<std::string, std::string> testdata{
{"Authentication=Basic xxx", "Authentication=Basic xxx"},
{"Authentication=Basic%20xxx", "Authentication=Basic xxx"},
{"%C3%B6%C3%A0%C2%A7%C3%96abcd%C3%84", "öà§ÖabcdÄ"},
{"%2x", "%2x"},
{"%20", " "},
{"text%2", "text%2"},
};

for (auto &testsample : testdata)
{
ASSERT_EQ(http_common::UrlDecoder::Decode(testsample.first), testsample.second);
ASSERT_TRUE(http_common::UrlDecoder::Decode(testsample.first) == testsample.second);
}
}

0 comments on commit e5c2e25

Please sign in to comment.