Skip to content

Commit

Permalink
Fix URI parse error (#2067)
Browse files Browse the repository at this point in the history
  • Loading branch information
trask authored Jan 24, 2022
1 parent 67c06bd commit 19713f1
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -125,9 +123,6 @@ public class Exporter implements SpanExporter {
private static final OperationLogger exportingSpanLogger =
new OperationLogger(Exporter.class, "Exporting span");

private static final OperationLogger parsingHttpUrlLogger =
new OperationLogger(Exporter.class, "Parsing http.url");

static {
Set<String> dbSystems = new HashSet<>();
dbSystems.add(SemanticAttributes.DbSystemValues.DB2);
Expand Down Expand Up @@ -547,18 +542,8 @@ private static String getTargetForHttpClientSpan(Attributes attributes) {
}
String url = attributes.get(SemanticAttributes.HTTP_URL);
if (url != null) {
URI uri;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
parsingHttpUrlLogger.recordFailure(e.getMessage(), e);
uri = null;
}
if (uri != null) {
target = uri.getHost();
if (uri.getPort() != 80 && uri.getPort() != 443 && uri.getPort() != -1) {
target += ":" + uri.getPort();
}
target = UrlParser.getTargetFromUrl(url);
if (target != null) {
return target;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,43 @@

class UrlParser {

/**
* Returns the "target" (host:port) portion of the url.
*
* <p>Returns {@code null} if the target cannot be extracted from url for any reason.
*/
@Nullable
static String getTargetFromUrl(String url) {

int schemeEndIndex = url.indexOf(':');
if (schemeEndIndex == -1) {
// not a valid url
return null;
}

int len = url.length();
if (schemeEndIndex + 2 < len
&& url.charAt(schemeEndIndex + 1) == '/'
&& url.charAt(schemeEndIndex + 2) == '/') {
// has authority component
// look for
// '/' - start of path
// '?' or end of string - empty path
int index;
for (index = schemeEndIndex + 3; index < len; index++) {
char c = url.charAt(index);
if (c == '/' || c == '?' || c == '#') {
break;
}
}
String target = url.substring(schemeEndIndex + 3, index);
return target.isEmpty() ? null : target;
} else {
// has no authority
return null;
}
}

/**
* Returns the path portion of the url.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import org.junit.jupiter.api.Test;

public class UrlParserTest {
public class UrlParserPathTest {

@Test
public void testGetPathFromUrl() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the ""Software""), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

package com.microsoft.applicationinsights.agent.internal.exporter;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class UrlParserTargetTest {

// there are more test cases here than needed, but they are just copied from UrlParserPathTest

@Test
public void testGetTargetFromUrl() {
assertThat(UrlParser.getTargetFromUrl("https://localhost")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path/")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path/")).isEqualTo("localhost");

assertThat(UrlParser.getTargetFromUrl("https://localhost?")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/?")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path?")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path/?")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path?")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path/?")).isEqualTo("localhost");

assertThat(UrlParser.getTargetFromUrl("https://localhost?query")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/?query")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path?query")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path/?query")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path?query"))
.isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path/?query"))
.isEqualTo("localhost");

assertThat(UrlParser.getTargetFromUrl("https://localhost#")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/#")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path#")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path/#")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path#")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path/#")).isEqualTo("localhost");

assertThat(UrlParser.getTargetFromUrl("https://localhost#fragment")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/#fragment")).isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path#fragment"))
.isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/path/#fragment"))
.isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path#fragment"))
.isEqualTo("localhost");
assertThat(UrlParser.getTargetFromUrl("https://localhost/more/path/#fragment"))
.isEqualTo("localhost");
}

@Test
public void testGetTargetFromUrlWithPort() {
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path/"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path/"))
.isEqualTo("localhost:8080");

assertThat(UrlParser.getTargetFromUrl("https://localhost:8080?")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/?")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path?"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path/?"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path?"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path/?"))
.isEqualTo("localhost:8080");

assertThat(UrlParser.getTargetFromUrl("https://localhost:8080?query"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/?query"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path?query"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path/?query"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path?query"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path/?query"))
.isEqualTo("localhost:8080");

assertThat(UrlParser.getTargetFromUrl("https://localhost:8080#")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/#")).isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path#"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path/#"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path#"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path/#"))
.isEqualTo("localhost:8080");

assertThat(UrlParser.getTargetFromUrl("https://localhost:8080#fragment"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/#fragment"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path#fragment"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/path/#fragment"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path#fragment"))
.isEqualTo("localhost:8080");
assertThat(UrlParser.getTargetFromUrl("https://localhost:8080/more/path/#fragment"))
.isEqualTo("localhost:8080");
}

@Test
public void testGetTargetFromUrlWithNoAuthority() {
assertThat(UrlParser.getTargetFromUrl("https:")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path/")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path/")).isNull();

assertThat(UrlParser.getTargetFromUrl("https:?")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/?")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path?")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path/?")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path?")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path/?")).isNull();

assertThat(UrlParser.getTargetFromUrl("https:?query")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/?query")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path?query")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path/?query")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path?query")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path/?query")).isNull();

assertThat(UrlParser.getTargetFromUrl("https:#")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/#")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path#")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path/#")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path#")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path/#")).isNull();

assertThat(UrlParser.getTargetFromUrl("https:#fragment")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/#fragment")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path#fragment")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/path/#fragment")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path#fragment")).isNull();
assertThat(UrlParser.getTargetFromUrl("https:/more/path/#fragment")).isNull();
}
}

0 comments on commit 19713f1

Please sign in to comment.