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]