Skip to content

Commit 482f15b

Browse files
authored
Merge branch 'main' into lcian/chore/reactor-apollo4-modules
2 parents c6713b7 + 44791e1 commit 482f15b

File tree

7 files changed

+196
-109
lines changed

7 files changed

+196
-109
lines changed

.github/ISSUE_TEMPLATE/bug_report_android.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: 🐞 Bug Report - Android
22
description: Tell us about something that's not working the way we (probably) intend.
33
labels: ["Platform: Android", "Type: Bug"]
4+
type: Bug
45
body:
56
- type: dropdown
67
id: integration

.github/ISSUE_TEMPLATE/bug_report_java.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: 🐞 Bug Report - Java
22
description: Tell us about something that's not working the way we (probably) intend.
33
labels: ["Platform: Java", "Type: Bug"]
4+
type: Bug
45
body:
56
- type: dropdown
67
id: integration

.github/ISSUE_TEMPLATE/feature_android.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: 💡 Feature Request - Android
22
description: Tell us about a problem our SDK could solve but doesn't.
33
labels: ["Platform: Android", "Type: Feature Request"]
4+
type: Feature
45
body:
56
- type: textarea
67
id: problem

.github/ISSUE_TEMPLATE/feature_java.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: 💡 Feature Request - Java
22
description: Tell us about a problem our SDK could solve but doesn't.
33
labels: ["Platform: Java", "Type: Feature Request"]
4+
type: Feature
45
body:
56
- type: textarea
67
id: problem

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
- The SDK now automatically propagates the trace-context to the native layer. This allows to connect errors on different layers of the application. ([#4137](https://github.com/getsentry/sentry-java/pull/4137))
66

7+
### Behavioural Changes
8+
9+
- Use `java.net.URI` for parsing URLs in `UrlUtils` ([#4210](https://github.com/getsentry/sentry-java/pull/4210))
10+
- This could affect grouping for issues with messages containing URLs that fall in known corner cases that were handled incorrectly previously (e.g. email in URL path)
11+
712
### Dependencies
813

914
- Bump Native SDK from v0.7.20 to v0.8.1 ([#4137](https://github.com/getsentry/sentry-java/pull/4137))

sentry/src/main/java/io/sentry/util/UrlUtils.java

Lines changed: 32 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import io.sentry.ISpan;
44
import io.sentry.SpanDataConvention;
55
import io.sentry.protocol.Request;
6-
import java.net.MalformedURLException;
7-
import java.net.URL;
8-
import java.util.regex.Matcher;
9-
import java.util.regex.Pattern;
6+
import java.net.URI;
107
import org.jetbrains.annotations.ApiStatus;
118
import org.jetbrains.annotations.NotNull;
129
import org.jetbrains.annotations.Nullable;
@@ -15,123 +12,55 @@
1512
public final class UrlUtils {
1613

1714
public static final @NotNull String SENSITIVE_DATA_SUBSTITUTE = "[Filtered]";
18-
private static final @NotNull Pattern AUTH_REGEX = Pattern.compile("(.+://)(.*@)(.*)");
1915

2016
public static @Nullable UrlDetails parseNullable(final @Nullable String url) {
21-
if (url == null) {
22-
return null;
23-
}
24-
25-
return parse(url);
17+
return url == null ? null : parse(url);
2618
}
2719

2820
public static @NotNull UrlDetails parse(final @NotNull String url) {
29-
if (isAbsoluteUrl(url)) {
30-
return splitAbsoluteUrl(url);
31-
} else {
32-
return splitRelativeUrl(url);
33-
}
34-
}
35-
36-
private static boolean isAbsoluteUrl(@NotNull String url) {
37-
return url.contains("://");
38-
}
39-
40-
private static @NotNull UrlDetails splitRelativeUrl(final @NotNull String url) {
41-
final int queryParamSeparatorIndex = url.indexOf("?");
42-
final int fragmentSeparatorIndex = url.indexOf("#");
43-
44-
final @Nullable String baseUrl =
45-
extractBaseUrl(url, queryParamSeparatorIndex, fragmentSeparatorIndex);
46-
final @Nullable String query =
47-
extractQuery(url, queryParamSeparatorIndex, fragmentSeparatorIndex);
48-
final @Nullable String fragment = extractFragment(url, fragmentSeparatorIndex);
21+
try {
22+
URI uri = new URI(url);
23+
if (uri.isAbsolute() && !isValidAbsoluteUrl(uri)) {
24+
return new UrlDetails(null, null, null);
25+
}
4926

50-
return new UrlDetails(baseUrl, query, fragment);
51-
}
27+
final @NotNull String schemeAndSeparator =
28+
uri.getScheme() == null ? "" : (uri.getScheme() + "://");
29+
final @NotNull String authority = uri.getRawAuthority() == null ? "" : uri.getRawAuthority();
30+
final @NotNull String path = uri.getRawPath() == null ? "" : uri.getRawPath();
31+
final @Nullable String query = uri.getRawQuery();
32+
final @Nullable String fragment = uri.getRawFragment();
5233

53-
private static @Nullable String extractBaseUrl(
54-
final @NotNull String url,
55-
final int queryParamSeparatorIndex,
56-
final int fragmentSeparatorIndex) {
57-
if (queryParamSeparatorIndex >= 0) {
58-
return url.substring(0, queryParamSeparatorIndex).trim();
59-
} else if (fragmentSeparatorIndex >= 0) {
60-
return url.substring(0, fragmentSeparatorIndex).trim();
61-
} else {
62-
return url;
63-
}
64-
}
34+
final @NotNull String filteredUrl = schemeAndSeparator + filterUserInfo(authority) + path;
6535

66-
private static @Nullable String extractQuery(
67-
final @NotNull String url,
68-
final int queryParamSeparatorIndex,
69-
final int fragmentSeparatorIndex) {
70-
if (queryParamSeparatorIndex > 0) {
71-
if (fragmentSeparatorIndex > 0 && fragmentSeparatorIndex > queryParamSeparatorIndex) {
72-
return url.substring(queryParamSeparatorIndex + 1, fragmentSeparatorIndex).trim();
73-
} else {
74-
return url.substring(queryParamSeparatorIndex + 1).trim();
75-
}
76-
} else {
77-
return null;
78-
}
79-
}
80-
81-
private static @Nullable String extractFragment(
82-
final @NotNull String url, final int fragmentSeparatorIndex) {
83-
if (fragmentSeparatorIndex > 0) {
84-
return url.substring(fragmentSeparatorIndex + 1).trim();
85-
} else {
86-
return null;
36+
return new UrlDetails(filteredUrl, query, fragment);
37+
} catch (Exception e) {
38+
return new UrlDetails(null, null, null);
8739
}
8840
}
8941

90-
private static @NotNull UrlDetails splitAbsoluteUrl(final @NotNull String url) {
42+
private static boolean isValidAbsoluteUrl(final @NotNull URI uri) {
9143
try {
92-
final @NotNull String filteredUrl = urlWithAuthRemoved(url);
93-
final @NotNull URL urlObj = new URL(url);
94-
final @NotNull String baseUrl = baseUrlOnly(filteredUrl);
95-
if (baseUrl.contains("#")) {
96-
// url considered malformed because it has fragment
97-
return new UrlDetails(null, null, null);
98-
} else {
99-
final @Nullable String query = urlObj.getQuery();
100-
final @Nullable String fragment = urlObj.getRef();
101-
return new UrlDetails(baseUrl, query, fragment);
102-
}
103-
} catch (MalformedURLException e) {
104-
return new UrlDetails(null, null, null);
44+
uri.toURL();
45+
} catch (Exception e) {
46+
return false;
10547
}
48+
return true;
10649
}
10750

108-
private static @NotNull String urlWithAuthRemoved(final @NotNull String url) {
109-
final @NotNull Matcher userInfoMatcher = AUTH_REGEX.matcher(url);
110-
if (userInfoMatcher.matches() && userInfoMatcher.groupCount() == 3) {
111-
final @NotNull String userInfoString = userInfoMatcher.group(2);
112-
final @NotNull String replacementString =
113-
userInfoString.contains(":")
114-
? (SENSITIVE_DATA_SUBSTITUTE + ":" + SENSITIVE_DATA_SUBSTITUTE + "@")
115-
: (SENSITIVE_DATA_SUBSTITUTE + "@");
116-
return userInfoMatcher.group(1) + replacementString + userInfoMatcher.group(3);
117-
} else {
51+
private static @NotNull String filterUserInfo(final @NotNull String url) {
52+
if (!url.contains("@")) {
11853
return url;
11954
}
120-
}
121-
122-
private static @NotNull String baseUrlOnly(final @NotNull String url) {
123-
final int queryParamSeparatorIndex = url.indexOf("?");
124-
125-
if (queryParamSeparatorIndex >= 0) {
126-
return url.substring(0, queryParamSeparatorIndex).trim();
127-
} else {
128-
final int fragmentSeparatorIndex = url.indexOf("#");
129-
if (fragmentSeparatorIndex >= 0) {
130-
return url.substring(0, fragmentSeparatorIndex).trim();
131-
} else {
132-
return url;
133-
}
55+
if (url.startsWith("@")) {
56+
return SENSITIVE_DATA_SUBSTITUTE + url;
13457
}
58+
final @NotNull String userInfo = url.substring(0, url.indexOf('@'));
59+
final @NotNull String filteredUserInfo =
60+
userInfo.contains(":")
61+
? (SENSITIVE_DATA_SUBSTITUTE + ":" + SENSITIVE_DATA_SUBSTITUTE)
62+
: SENSITIVE_DATA_SUBSTITUTE;
63+
return filteredUserInfo + url.substring(url.indexOf('@'));
13564
}
13665

13766
public static final class UrlDetails {

0 commit comments

Comments
 (0)