Skip to content

Commit 2caa7b1

Browse files
committed
Safer endpoint Uri construction
Make endpoint Uri construction less fragile by stripping out duplicate slahes.
1 parent c05b23d commit 2caa7b1

File tree

1 file changed

+28
-5
lines changed
  • opentelemetry-otlp/src/exporter/http

1 file changed

+28
-5
lines changed

opentelemetry-otlp/src/exporter/http/mod.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,15 @@ impl OtlpHttpClient {
286286
}
287287
}
288288

289+
fn build_endpoint_uri(endpoint: &str, path: &str) -> Result<Uri, crate::Error> {
290+
let path = if endpoint.ends_with('/') && path.starts_with('/') {
291+
path.strip_prefix('/').unwrap()
292+
} else {
293+
path
294+
};
295+
format!("{endpoint}{path}").parse().map_err(From::from)
296+
}
297+
289298
// see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#endpoint-urls-for-otlphttp
290299
fn resolve_endpoint(
291300
signal_endpoint_var: &str,
@@ -303,15 +312,13 @@ fn resolve_endpoint(
303312
// if signal env var is not set, then we check if the OTEL_EXPORTER_OTLP_ENDPOINT is set
304313
if let Some(endpoint) = env::var(OTEL_EXPORTER_OTLP_ENDPOINT)
305314
.ok()
306-
.and_then(|s| format!("{s}{signal_endpoint_path}").parse().ok())
315+
.and_then(|s| build_endpoint_uri(&s, signal_endpoint_path).ok())
307316
{
308317
return Ok(endpoint);
309318
}
310319

311-
// if neither works, we use the one provided in pipeline. If user never provide one, we will use the default one
312-
format!("{provided_or_default_endpoint}{signal_endpoint_path}")
313-
.parse()
314-
.map_err(From::from)
320+
// if neither works, we use the one provided in pipeline. If user never provides one, we will use the default one
321+
build_endpoint_uri(provided_or_default_endpoint, signal_endpoint_path)
315322
}
316323

317324
#[allow(clippy::mutable_key_type)] // http headers are not mutated
@@ -329,6 +336,8 @@ mod tests {
329336
use crate::exporter::tests::run_env_test;
330337
use crate::{OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT};
331338

339+
use super::build_endpoint_uri;
340+
332341
#[test]
333342
fn test_append_signal_path_to_generic_env() {
334343
run_env_test(
@@ -390,6 +399,20 @@ mod tests {
390399
});
391400
}
392401

402+
#[test]
403+
fn test_build_endpoint_uri() {
404+
let uri = build_endpoint_uri("https://example.com", "/v1/traces").unwrap();
405+
assert_eq!(uri, "https://example.com/v1/traces");
406+
407+
// Should be no duplicate slahes:
408+
let uri = build_endpoint_uri("https://example.com/", "/v1/traces").unwrap();
409+
assert_eq!(uri, "https://example.com/v1/traces");
410+
411+
// Append paths properly:
412+
let uri = build_endpoint_uri("https://example.com/additional/path/", "/v1/traces").unwrap();
413+
assert_eq!(uri, "https://example.com/additional/path/v1/traces");
414+
}
415+
393416
#[test]
394417
fn test_invalid_uri_in_signal_env_falls_back_to_generic_env() {
395418
run_env_test(

0 commit comments

Comments
 (0)