@@ -286,6 +286,15 @@ impl OtlpHttpClient {
286
286
}
287
287
}
288
288
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
+
289
298
// see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#endpoint-urls-for-otlphttp
290
299
fn resolve_endpoint (
291
300
signal_endpoint_var : & str ,
@@ -303,15 +312,13 @@ fn resolve_endpoint(
303
312
// if signal env var is not set, then we check if the OTEL_EXPORTER_OTLP_ENDPOINT is set
304
313
if let Some ( endpoint) = env:: var ( OTEL_EXPORTER_OTLP_ENDPOINT )
305
314
. ok ( )
306
- . and_then ( |s| format ! ( "{s}{ signal_endpoint_path}" ) . parse ( ) . ok ( ) )
315
+ . and_then ( |s| build_endpoint_uri ( & s , signal_endpoint_path) . ok ( ) )
307
316
{
308
317
return Ok ( endpoint) ;
309
318
}
310
319
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)
315
322
}
316
323
317
324
#[ allow( clippy:: mutable_key_type) ] // http headers are not mutated
@@ -329,6 +336,8 @@ mod tests {
329
336
use crate :: exporter:: tests:: run_env_test;
330
337
use crate :: { OTEL_EXPORTER_OTLP_ENDPOINT , OTEL_EXPORTER_OTLP_TRACES_ENDPOINT } ;
331
338
339
+ use super :: build_endpoint_uri;
340
+
332
341
#[ test]
333
342
fn test_append_signal_path_to_generic_env ( ) {
334
343
run_env_test (
@@ -390,6 +399,20 @@ mod tests {
390
399
} ) ;
391
400
}
392
401
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
+
393
416
#[ test]
394
417
fn test_invalid_uri_in_signal_env_falls_back_to_generic_env ( ) {
395
418
run_env_test (
0 commit comments