You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hugegraph.apache.org by ji...@apache.org on 2026/10/07 14:38:41 UTC

(hugegraph) branch master updated: fix(common): encode REST bodies as UTF-8 (#3281)

This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph.git


The following commit(s) were added to refs/heads/master by this push:
     new e62c961e0 fix(common): encode REST bodies as UTF-8 (#3281)
e62c961e0 is described below

commit e62c961e00221569d4f955abbadf60faee45b283
Author: imbajin <ji...@apache.org>
AuthorDate: Wed Oct 7 22:38:36 2026 +0800

    fix(common): encode REST bodies as UTF-8 (#3281)
    
    OkHttp encodes text request bodies as UTF-8 by default and declares the charset. Explicit caller-provided charsets remain supported.
---
 .../apache/hugegraph/rest/AbstractRestClient.java  |   2 +-
 .../unit/rest/AbstractRestClientTest.java          | 104 +++++++++++++++++++++
 2 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
index c13a686b7..91fa90bf2 100644
--- a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
@@ -138,7 +138,7 @@ public abstract class AbstractRestClient implements RestClient {
         } else {
             bodyContent = String.valueOf(body);
         }
-        RequestBody requestBody = RequestBody.create(bodyContent.getBytes(),
+        RequestBody requestBody = RequestBody.create(bodyContent,
                                                      MediaType.parse(contentType));
 
         if (headers != null &&
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java
index b2d2b1a3b..a19e44592 100644
--- a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java
@@ -17,12 +17,116 @@
 
 package org.apache.hugegraph.unit.rest;
 
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.hugegraph.rest.AbstractRestClient;
+import org.apache.hugegraph.rest.RestHeaders;
+import org.apache.hugegraph.testutil.Whitebox;
 import org.junit.Assert;
 import org.junit.Test;
 
+import okhttp3.RequestBody;
+import okio.Buffer;
+import okio.GzipSource;
+
 public class AbstractRestClientTest {
 
+    @Test
+    public void testRequestBodiesWithAsciiDefaultCharset() throws Exception {
+        String java = Paths.get(System.getProperty("java.home"), "bin", "java").toString();
+        String classpath = System.getProperty("surefire.test.class.path",
+                                              System.getProperty("java.class.path"));
+        Path output = Files.createTempFile("rest-client-ascii-", ".log");
+        Process process = null;
+        try {
+            process = new ProcessBuilder(java, "-Dfile.encoding=US-ASCII", "-cp", classpath,
+                                         AsciiRequestBodyProbe.class.getName())
+                    .redirectErrorStream(true)
+                    .redirectOutput(output.toFile())
+                    .start();
+            boolean finished = process.waitFor(60, TimeUnit.SECONDS);
+            String diagnostic = Files.readString(output, StandardCharsets.UTF_8);
+            Assert.assertTrue("US-ASCII probe timed out: " + diagnostic, finished);
+            Assert.assertEquals(diagnostic, 0, process.exitValue());
+        } finally {
+            if (process != null && process.isAlive()) {
+                process.destroyForcibly();
+                process.waitFor(5, TimeUnit.SECONDS);
+            }
+            Files.deleteIfExists(output);
+        }
+    }
+
+    public static class AsciiRequestBodyProbe {
+
+        public static void main(String[] args) throws IOException {
+            Assert.assertEquals(StandardCharsets.US_ASCII, Charset.defaultCharset());
+            AbstractRestClientTest tests = new AbstractRestClientTest();
+            tests.testJsonRequestBodyUsesUtf8();
+            tests.testGzipRequestBodyUsesUtf8();
+            tests.testRequestBodyRespectsExplicitCharset();
+        }
+    }
+
+    @Test
+    public void testJsonRequestBodyUsesUtf8() throws IOException {
+        String json = "{\"id\":\"\u4f60\u597d\ud83d\ude80\"}";
+        assertUtf8Body(json, null, json, false);
+        assertUtf8Body(Collections.singletonMap("id", "\u4f60\u597d\ud83d\ude80"),
+                       new RestHeaders(), json, false);
+    }
+
+    @Test
+    public void testGzipRequestBodyUsesUtf8() throws IOException {
+        String json = "{\"id\":\"\u4f60\u597d\ud83d\ude80\"}";
+        RestHeaders headers = new RestHeaders().add(RestHeaders.CONTENT_ENCODING, "gzip");
+        assertUtf8Body(json, headers, json, true);
+    }
+
+    @Test
+    public void testRequestBodyRespectsExplicitCharset() throws IOException {
+        RestHeaders headers = new RestHeaders().add(RestHeaders.CONTENT_TYPE,
+                                                    "text/plain; charset=iso-8859-1");
+        RequestBody body = requestBody("caf\u00e9", headers);
+        Buffer buffer = new Buffer();
+        body.writeTo(buffer);
+        Assert.assertEquals(StandardCharsets.ISO_8859_1, body.contentType().charset());
+        Assert.assertArrayEquals("caf\u00e9".getBytes(StandardCharsets.ISO_8859_1),
+                                 buffer.readByteArray());
+    }
+
+    private static void assertUtf8Body(Object value, RestHeaders headers,
+                                      String expected, boolean gzip) throws IOException {
+        RequestBody body = requestBody(value, headers);
+        Assert.assertEquals(StandardCharsets.UTF_8, body.contentType().charset());
+        Buffer buffer = new Buffer();
+        body.writeTo(buffer);
+        if (gzip) {
+            try (GzipSource source = new GzipSource(buffer)) {
+                Buffer decoded = new Buffer();
+                decoded.writeAll(source);
+                Assert.assertArrayEquals(expected.getBytes(StandardCharsets.UTF_8),
+                                         decoded.readByteArray());
+            }
+        } else {
+            Assert.assertArrayEquals(expected.getBytes(StandardCharsets.UTF_8),
+                                     buffer.readByteArray());
+        }
+    }
+
+    private static RequestBody requestBody(Object value, RestHeaders headers) {
+        return Whitebox.invokeStatic(AbstractRestClient.class,
+                                     new Class<?>[]{Object.class, RestHeaders.class},
+                                     "buildRequestBody", value, headers);
+    }
+
     @Test
     public void testEncodeWithSpaces() {
         String raw = "hello world";