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


##########
discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java:
##########
@@ -498,12 +495,12 @@ private static void acquireClusterMetaData(String 
clusterName, String group) thr
             Map<String, String> param = new HashMap<>();
             param.put("group", group);
             String response = null;
-            try (CloseableHttpResponse httpResponse =
+            try (Response httpResponse =
                     HttpClientUtil.doGet("http://"; + tcAddress + 
"/metadata/v1/cluster", param, header, 1000)) {
                 if (httpResponse != null) {
-                    int statusCode = 
httpResponse.getStatusLine().getStatusCode();
+                    int statusCode = httpResponse.code();
                     if (statusCode == HttpStatus.SC_OK) {
-                        response = 
EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
+                        response = httpResponse.body().string();

Review Comment:
   Potential NullPointerException when calling response.body().string(). The 
OkHttp Response.body() method can return null. While the response object itself 
is checked for null, the body should also be checked before calling string() to 
avoid NPE.
   ```suggestion
                           if (httpResponse.body() != null) {
                               response = httpResponse.body().string();
                           } else {
                               LOGGER.warn("Received HTTP 200 from {} but 
response body is null for group: {}", tcAddress, group);
                           }
   ```



##########
discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImpl.java:
##########
@@ -576,11 +572,11 @@ private static void refreshToken(String 
namingServerAddress) throws RetryableExc
         Map<String, String> header = new HashMap<>();
         header.put(HTTP.CONTENT_TYPE, 
ContentType.APPLICATION_JSON.getMimeType());
         String response = null;
-        try (CloseableHttpResponse httpResponse =
+        try (Response httpResponse =
                 HttpClientUtil.doPost("http://"; + namingServerAddress + 
"/api/v1/auth/login", param, header, 1000)) {
             if (httpResponse != null) {
-                if (httpResponse.getStatusLine().getStatusCode() == 
HttpStatus.SC_OK) {
-                    response = EntityUtils.toString(httpResponse.getEntity(), 
StandardCharsets.UTF_8);
+                if (httpResponse.code() == HttpStatus.SC_OK) {

Review Comment:
   Potential NullPointerException when calling response.body().string(). The 
OkHttp Response.body() method can return null. While the response object itself 
is checked for null, the body should also be checked before calling string() to 
avoid NPE.
   ```suggestion
                   if (httpResponse.code() == HttpStatus.SC_OK) {
                       if (httpResponse.body() == null) {
                           throw new RetryableException("Empty response body 
from naming server auth login.");
                       }
   ```



##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -305,6 +219,24 @@ private static OkHttpClient 
createHttp2ClientWithTimeout(int timeoutSeconds) {
                 .build());
     }
 
+    private static Request buildHttp1Request(
+            String url, Map<String, String> headers, RequestBody requestBody, 
String method) {
+        Headers.Builder headerBuilder = new Headers.Builder();
+        if (headers != null) {
+            headers.forEach(headerBuilder::add);
+        }
+
+        Request.Builder requestBuilder = new 
Request.Builder().url(url).headers(headerBuilder.build());
+
+        if ("POST".equals(method) && requestBody != null) {
+            requestBuilder.post(requestBody);
+        } else if ("GET".equals(method)) {
+            requestBuilder.get();
+        }
+
+        return requestBuilder.build();

Review Comment:
   When the method is "POST" but requestBody is null, the request builder 
doesn't call post() and falls through to build() which creates a GET request by 
default in OkHttp. This can happen when doPost is called with a null body 
parameter. The method should either provide an empty RequestBody for POST 
requests or throw an exception to prevent silent behavior change.



##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -323,6 +255,32 @@ private static Request buildHttp2Request(
         return requestBuilder.build();
     }
 
+    private static String buildUrlWithParams(String url, Map<String, String> 
params) {
+        if (params == null || params.isEmpty()) {
+            return url;
+        }
+        StringBuilder urlBuilder = new StringBuilder(url);
+        boolean first = !url.contains("?");
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            if (first) {
+                urlBuilder.append("?");
+                first = false;
+            } else {
+                urlBuilder.append("&");
+            }
+            try {
+                urlBuilder
+                        .append(URLEncoder.encode(entry.getKey(), 
StandardCharsets.UTF_8.toString()))
+                        .append("=")
+                        .append(URLEncoder.encode(entry.getValue(), 
StandardCharsets.UTF_8.toString()));

Review Comment:
   The URLEncoder.encode() method with String parameter is deprecated as of 
Java 10. Use URLEncoder.encode(String, Charset) or URLEncoder.encode(String, 
String) without calling toString() on the Charset. The current code is 
unnecessarily converting StandardCharsets.UTF_8 to a String.
   ```suggestion
                           .append(URLEncoder.encode(entry.getKey(), 
StandardCharsets.UTF_8.name()))
                           .append("=")
                           .append(URLEncoder.encode(entry.getValue(), 
StandardCharsets.UTF_8.name()));
   ```



##########
discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImpl.java:
##########
@@ -438,12 +434,12 @@ public List<InetSocketAddress> refreshGroup(String 
vGroup) throws IOException, R
         if (StringUtils.isNotBlank(jwtToken)) {
             header.put(AUTHORIZATION_HEADER, jwtToken);
         }
-        try (CloseableHttpResponse response = HttpClientUtil.doGet(url, 
paraMap, header, 3000)) {
-            if (response == null || response.getStatusLine().getStatusCode() 
!= HttpStatus.SC_OK) {
+        try (Response response = HttpClientUtil.doGet(url, paraMap, header, 
3000)) {
+            if (response == null || response.code() != HttpStatus.SC_OK) {
                 throw new NamingRegistryException("cannot lookup server list 
in vgroup: " + vGroup + ", http code: "
-                        + response.getStatusLine().getStatusCode());
+                        + (response != null ? response.code() : -1));
             }
-            String jsonResponse = EntityUtils.toString(response.getEntity(), 
StandardCharsets.UTF_8);
+            String jsonResponse = response.body().string();

Review Comment:
   Potential NullPointerException when calling response.body().string(). The 
OkHttp Response.body() method can return null. While the response object itself 
is checked for null, the body should also be checked before calling string() to 
avoid NPE.



##########
discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java:
##########
@@ -544,11 +541,11 @@ private static void refreshToken(String tcAddress) throws 
RetryableException {
         Map<String, String> header = new HashMap<>();
         header.put(HTTP.CONTENT_TYPE, 
ContentType.APPLICATION_JSON.getMimeType());
         String response = null;
-        try (CloseableHttpResponse httpResponse =
+        try (Response httpResponse =
                 HttpClientUtil.doPost("http://"; + tcAddress + 
"/api/v1/auth/login", param, header, 1000)) {
             if (httpResponse != null) {
-                if (httpResponse.getStatusLine().getStatusCode() == 
HttpStatus.SC_OK) {
-                    response = EntityUtils.toString(httpResponse.getEntity(), 
StandardCharsets.UTF_8);
+                if (httpResponse.code() == HttpStatus.SC_OK) {
+                    response = httpResponse.body().string();

Review Comment:
   Potential NullPointerException when calling response.body().string(). The 
OkHttp Response.body() method can return null. While the response object itself 
is checked for null, the body should also be checked before calling string() to 
avoid NPE.
   ```suggestion
                       okhttp3.ResponseBody responseBody = httpResponse.body();
                       if (responseBody == null) {
                           // authorized failed,throw exception to kill process
                           throw new AuthenticationFailedException(
                                   "Authentication failed! empty response body, 
please check the server configuration.");
                       }
                       response = responseBody.string();
   ```



##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -295,6 +200,15 @@ private static RequestBody createRequestBody(Map<String, 
String> params, String
         }
     }
 
+    private static OkHttpClient createHttp1ClientWithTimeout(int 
timeoutSeconds) {
+        return HTTP_CLIENT_MAP.computeIfAbsent(timeoutSeconds, k -> new 
OkHttpClient.Builder()
+                // Use HTTP/1.1 (default protocol, no need to specify)
+                .connectTimeout(timeoutSeconds, TimeUnit.SECONDS)
+                .readTimeout(timeoutSeconds, TimeUnit.SECONDS)
+                .writeTimeout(timeoutSeconds, TimeUnit.SECONDS)
+                .build());
+    }

Review Comment:
   The timeout parameter is being interpreted as seconds, but all callers are 
passing values in milliseconds (e.g., 1000, 3000, 30000). This creates 
extremely long timeouts that don't match the original Apache HttpClient 
behavior. The parameter should either be converted from milliseconds to 
seconds, or the TimeUnit should be changed to MILLISECONDS to maintain backward 
compatibility with the original API.



##########
common/pom.xml:
##########
@@ -43,11 +43,11 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
-        <dependency>
+        <!--<dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <scope>provided</scope>
-        </dependency>
+        </dependency>-->

Review Comment:
   The httpclient dependency is commented out but should be completely removed 
if it's no longer needed. Leaving commented-out code in production can cause 
confusion about whether it should be restored or removed permanently. Consider 
removing it entirely or documenting why it's being kept.



##########
common/src/main/java/org/apache/seata/common/util/HttpClientUtil.java:
##########
@@ -107,130 +93,49 @@ public class HttpClientUtil {
     }
 
     // post request
-    public static CloseableHttpResponse doPost(
-            String url, Map<String, String> params, Map<String, String> 
header, int timeout) throws IOException {
+    public static Response doPost(String url, Map<String, String> params, 
Map<String, String> header, int timeout)
+            throws IOException {
         try {
-            URIBuilder builder = new URIBuilder(url);
-            URI uri = builder.build();
-            HttpPost httpPost = new HttpPost(uri);
-            String contentType = "";
-            if (header != null) {
-                header.forEach(httpPost::addHeader);
-                contentType = header.get("Content-Type");
-            }
-            if (StringUtils.isNotBlank(contentType)) {
-                if 
(ContentType.APPLICATION_FORM_URLENCODED.getMimeType().equals(contentType)) {
-                    List<NameValuePair> nameValuePairs = new ArrayList<>();
-                    params.forEach((k, v) -> {
-                        nameValuePairs.add(new BasicNameValuePair(k, v));
-                    });
-                    String requestBody = 
URLEncodedUtils.format(nameValuePairs, StandardCharsets.UTF_8);
-                    StringEntity stringEntity = new StringEntity(requestBody, 
ContentType.APPLICATION_FORM_URLENCODED);
-                    httpPost.setEntity(stringEntity);
-                } else if 
(ContentType.APPLICATION_JSON.getMimeType().equals(contentType)) {
-                    String requestBody = 
OBJECT_MAPPER.writeValueAsString(params);
-                    StringEntity stringEntity = new StringEntity(requestBody, 
ContentType.APPLICATION_JSON);
-                    httpPost.setEntity(stringEntity);
-                }
-            }
-            CloseableHttpClient client = 
HTTP_CLIENT_MAP.computeIfAbsent(timeout, k -> HttpClients.custom()
-                    
.setConnectionManager(POOLING_HTTP_CLIENT_CONNECTION_MANAGER)
-                    .setDefaultRequestConfig(RequestConfig.custom()
-                            .setConnectionRequestTimeout(timeout)
-                            .setSocketTimeout(timeout)
-                            .setConnectTimeout(timeout)
-                            .build())
-                    .build());
-            return client.execute(httpPost);
-        } catch (URISyntaxException | ClientProtocolException e) {
+            String contentType = header != null ? header.get("Content-Type") : 
"";
+            RequestBody requestBody = createRequestBody(params, contentType);
+            Request request = buildHttp1Request(url, header, requestBody, 
"POST");
+            OkHttpClient client = createHttp1ClientWithTimeout(timeout);
+            return client.newCall(request).execute();
+        } catch (JsonProcessingException e) {
             LOGGER.error(e.getMessage(), e);
+            throw new IOException("Failed to create request body", e);
         }
-        return null;
     }
 
     // post request
-    public static CloseableHttpResponse doPost(String url, String body, 
Map<String, String> header, int timeout)
-            throws IOException {
-        try {
-            URIBuilder builder = new URIBuilder(url);
-            URI uri = builder.build();
-            HttpPost httpPost = new HttpPost(uri);
-            String contentType = "";
-            if (header != null) {
-                header.forEach(httpPost::addHeader);
-                contentType = header.get("Content-Type");
-            }
-            if (StringUtils.isNotBlank(contentType)) {
-                if 
(ContentType.APPLICATION_JSON.getMimeType().equals(contentType)) {
-                    StringEntity stringEntity = new StringEntity(body, 
ContentType.APPLICATION_JSON);
-                    httpPost.setEntity(stringEntity);
-                }
-            }
-            CloseableHttpClient client = 
HTTP_CLIENT_MAP.computeIfAbsent(timeout, k -> HttpClients.custom()
-                    
.setConnectionManager(POOLING_HTTP_CLIENT_CONNECTION_MANAGER)
-                    .setDefaultRequestConfig(RequestConfig.custom()
-                            .setConnectionRequestTimeout(timeout)
-                            .setSocketTimeout(timeout)
-                            .setConnectTimeout(timeout)
-                            .build())
-                    .build());
-            return client.execute(httpPost);
-        } catch (URISyntaxException | ClientProtocolException e) {
-            LOGGER.error(e.getMessage(), e);
-        }
-        return null;
+    public static Response doPost(String url, String body, Map<String, String> 
header, int timeout) throws IOException {
+        String contentType = header != null ? header.get("Content-Type") : "";
+        MediaType mediaType = StringUtils.isNotBlank(contentType) ? 
MediaType.parse(contentType) : MEDIA_TYPE_JSON;
+        RequestBody requestBody = RequestBody.create(body, mediaType);

Review Comment:
   Calling RequestBody.create() with a null body string will cause a 
NullPointerException in OkHttp. The method should handle null body parameter by 
either creating an empty request body or throwing an appropriate exception with 
a clear error message.



-- 
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