This is an automated email from the ASF dual-hosted git repository.
smengcl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 63a45965ca4 HDDS-16749. Avoid regex compilation when splitting
canonical URIs for S3 signatures (#11460)
63a45965ca4 is described below
commit 63a45965ca4a20df9f61d8df1cb8431a120f8049
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Sat Oct 10 12:48:21 2026 +0800
HDDS-16749. Avoid regex compilation when splitting canonical URIs for S3
signatures (#11460)
---
.../ozone/s3/signature/StringToSignProducer.java | 25 +-------------------
.../s3/signature/TestStringToSignProducer.java | 27 ++++++++++++++++++----
2 files changed, 24 insertions(+), 28 deletions(-)
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
index 793669beda8..c6edbd30a10 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
@@ -34,8 +34,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.MultivaluedMap;
@@ -154,9 +152,8 @@ public static String buildCanonicalRequest(
String payloadHash
) throws OS3Exception {
- Iterable<String> parts = split("/", uri);
List<String> encParts = new ArrayList<>();
- for (String p : parts) {
+ for (String p : StringUtils.splitPreserveAllTokens(uri, '/')) {
encParts.add(urlEncode(p));
}
String canonicalUri = join("/", encParts);
@@ -210,26 +207,6 @@ private static String join(String glue, List<String>
parts) {
return result.toString();
}
- /**
- * Returns matching strings.
- *
- * @param regex Regular expression to split by
- * @param whole The string to split
- * @return pieces
- */
- private static Iterable<String> split(String regex, String whole) {
- Pattern p = Pattern.compile(regex);
- Matcher m = p.matcher(whole);
- List<String> result = new ArrayList<>();
- int pos = 0;
- while (m.find()) {
- result.add(whole.substring(pos, m.start()));
- pos = m.end();
- }
- result.add(whole.substring(pos));
- return result;
- }
-
private static String urlEncode(String str) {
try {
return StringUtils.replaceEach(S3Utils.urlEncode(str),
URL_ENCODE_SEARCH_CHARS, URL_ENCODE_REPLACE_CHARS);
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
index ba95cab32c6..565293fe907 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
@@ -118,8 +118,27 @@ public void test() throws Exception {
signatureBase, "String to sign is invalid");
}
- @Test
- public void testUrlEncodeInCanonicalRequest() {
+ private static Stream<Arguments> testUrlEncodeInCanonicalRequestInput() {
+ return Stream.of(
+ arguments("/bucket/a+b*c~d/foo bar", "/bucket/a%2Bb%2Ac~d/foo%20bar"),
+ arguments("", ""),
+ arguments("/", "/"),
+ arguments("//", "//"),
+ arguments("/bucket/", "/bucket/"),
+ arguments("//bucket/key", "//bucket/key"),
+ arguments("/bucket//key/", "/bucket//key/"),
+ arguments("/bucket/a/.././b", "/bucket/a/.././b"),
+ arguments("bucket/key", "bucket/key"),
+ // A literal %2F in the decoded path corresponds to %252F in the wire
path.
+ arguments("/bucket/a%2Fb", "/bucket/a%252Fb"),
+ arguments("/bucket/雪/😀", "/bucket/%E9%9B%AA/%F0%9F%98%80"),
+ arguments("/bucket/?#", "/bucket/%3F%23")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testUrlEncodeInCanonicalRequestInput")
+ public void testUrlEncodeInCanonicalRequest(String uri, String
expectedCanonicalUri) {
final Map<String, String> headers = new HashMap<>();
headers.put("host", "example.com");
headers.put("x-amz-content-sha256", UNSIGNED_PAYLOAD);
@@ -129,12 +148,12 @@ public void testUrlEncodeInCanonicalRequest() {
queryParams.put("q+1*2~3", "v 4*5~6");
final String canonicalRequest = StringToSignProducer.buildCanonicalRequest(
- "GET", "/bucket/a+b*c~d/foo bar",
"host;x-amz-content-sha256;x-amz-date",
+ "GET", uri, "host;x-amz-content-sha256;x-amz-date",
headers, queryParams, UNSIGNED_PAYLOAD);
assertEquals(
"GET\n"
- + "/bucket/a%2Bb%2Ac~d/foo%20bar\n"
+ + expectedCanonicalUri + "\n"
+ "q%2B1%2A2~3=v%204%2A5~6\n"
+ "host:example.com\n"
+ "x-amz-content-sha256:" + UNSIGNED_PAYLOAD + "\n"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]