Copilot commented on code in PR #7736:
URL: https://github.com/apache/incubator-seata/pull/7736#discussion_r2467624192


##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -195,4 +224,114 @@ public static CloseableHttpResponse doPostJson(
         CloseableHttpClient client = HttpClients.createDefault();
         return client.execute(post);
     }
+
+    public static void doPostWithHttp2(
+            String url, Map<String, String> params, Map<String, String> 
headers, HttpCallback<Response> callback) {
+        doPostWithHttp2(url, params, headers, callback, 10);
+    }
+
+    public static void doPostWithHttp2(
+            String url,
+            Map<String, String> params,
+            Map<String, String> headers,
+            HttpCallback<Response> callback,
+            int timeoutSeconds) {
+        try {
+            String contentType = headers != null ? headers.get("Content-Type") 
: "";
+            RequestBody requestBody = createRequestBody(params, contentType);
+            Request request = buildHttp2Request(url, headers, requestBody, 
"POST");
+            OkHttpClient client = createHttp2ClientWithTimeout(timeoutSeconds);
+            executeAsync(client, request, callback);
+        } catch (JsonProcessingException e) {
+            LOGGER.error(e.getMessage(), e);
+            callback.onFailure(e);
+        }
+    }
+
+    public static void doPostWithHttp2(
+            String url, String body, Map<String, String> headers, 
HttpCallback<Response> callback) {
+        // default timeout 10 seconds
+        doPostWithHttp2(url, body, headers, callback, 10);
+    }
+
+    public static void doPostWithHttp2(
+            String url, String body, Map<String, String> headers, 
HttpCallback<Response> callback, int timeoutSeconds) {
+        RequestBody requestBody = RequestBody.create(body, MEDIA_TYPE_JSON);
+        Request request = buildHttp2Request(url, headers, requestBody, "POST");
+        OkHttpClient client = createHttp2ClientWithTimeout(timeoutSeconds);
+        executeAsync(client, request, callback);
+    }
+
+    public static void doGetWithHttp2(
+            String url, Map<String, String> headers, final 
HttpCallback<Response> callback, int timeoutSeconds) {
+        Request request = buildHttp2Request(url, headers, null, "GET");
+        OkHttpClient client = createHttp2ClientWithTimeout(timeoutSeconds);
+        executeAsync(client, request, callback);
+    }
+
+    private static RequestBody createRequestBody(Map<String, String> params, 
String contentType)
+            throws JsonProcessingException {
+        if (params == null || params.isEmpty()) {
+            return RequestBody.create(new byte[0]);
+        }
+
+        if (MEDIA_TYPE_FORM_URLENCODED.toString().equals(contentType)) {

Review Comment:
   The string comparison using `equals()` will fail if the content-type header 
includes additional parameters (e.g., 'application/x-www-form-urlencoded; 
charset=UTF-8'). Use `contains()` or extract the media type without parameters 
for robust matching.
   ```suggestion
           // Extract media type without parameters for robust comparison
           String mediaTypeOnly = contentType == null ? "" : 
contentType.split(";")[0].trim();
           if (MEDIA_TYPE_FORM_URLENCODED.toString().equals(mediaTypeOnly)) {
   ```



##########
core/src/main/java/org/apache/seata/core/rpc/netty/http/Http2HttpHandler.java:
##########
@@ -111,12 +113,27 @@ private void handleRequest(ChannelHandlerContext ctx) {
             if (request.getMethod() == HttpMethod.POST
                     && request.getBody() != null
                     && !request.getBody().isEmpty()) {
-                // assume body is json
+                CharSequence contentTypeSeq = 
request.getHeaders().get(HttpHeaderNames.CONTENT_TYPE);
+                String contentType = contentTypeSeq != null ? 
contentTypeSeq.toString() : "";
+
                 try {
-                    ObjectNode bodyDataNode = (ObjectNode) 
OBJECT_MAPPER.readTree(request.getBody());
-                    requestDataNode.set("body", bodyDataNode);
+                    if (contentType.contains("application/json")) {
+                        ObjectNode bodyDataNode = (ObjectNode) 
OBJECT_MAPPER.readTree(request.getBody());
+                        requestDataNode.set("body", bodyDataNode);
+                    } else if 
(contentType.contains("application/x-www-form-urlencoded")) {
+                        Map<String, String> formParams = new HashMap<>();
+                        String[] pairs = request.getBody().split("&");
+                        for (String pair : pairs) {
+                            String[] kv = pair.split("=", 2);
+                            if (kv.length == 2) {
+                                formParams.put(kv[0], kv[1]);
+                            }
+                        }

Review Comment:
   Form parameter values are not URL-decoded. When parsing 
'application/x-www-form-urlencoded' data, values must be decoded using 
`URLDecoder.decode()` to properly handle special characters and encoded spaces.



##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -57,18 +73,31 @@ public class HttpClientUtil {
     static {
         POOLING_HTTP_CLIENT_CONNECTION_MANAGER.setMaxTotal(10);
         POOLING_HTTP_CLIENT_CONNECTION_MANAGER.setDefaultMaxPerRoute(10);
-        Runtime.getRuntime().addShutdownHook(new Thread(() -> 
HTTP_CLIENT_MAP.values().parallelStream()
-                .forEach(client -> {
-                    try {
-                        // delay 3s, make sure unregister http request send 
successfully
-                        Thread.sleep(3000);
-                        client.close();
-                    } catch (IOException | InterruptedException e) {
-                        LOGGER.error(e.getMessage(), e);
-                    }
-                })));
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            HTTP_CLIENT_MAP.values().parallelStream().forEach(client -> {
+                try {
+                    // delay 3s, make sure unregister http request send 
successfully
+                    Thread.sleep(3000);
+                    client.close();
+                } catch (IOException | InterruptedException e) {
+                    LOGGER.error(e.getMessage(), e);
+                }
+            });
+
+            HTTP2_CLIENT_MAP.values().parallelStream().forEach(client -> {
+                try {
+                    client.dispatcher().executorService().shutdown();
+                    client.connectionPool().evictAll();

Review Comment:
   Shutting down the OkHttp dispatcher's executor service without waiting for 
termination may cause in-flight requests to be abruptly terminated. Consider 
calling `awaitTermination()` with a timeout after `shutdown()` to allow 
graceful completion of pending requests.
   ```suggestion
                       client.dispatcher().executorService().shutdown();
                       // Wait for up to 3 seconds for in-flight requests to 
complete
                       if 
(!client.dispatcher().executorService().awaitTermination(3, TimeUnit.SECONDS)) {
                           LOGGER.warn("Timeout waiting for OkHttp executor 
service to terminate.");
                       }
                       client.connectionPool().evictAll();
                   } catch (InterruptedException e) {
                       Thread.currentThread().interrupt();
                       LOGGER.error("Interrupted while waiting for OkHttp 
executor service to terminate.", e);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to