• 107 在携带请求体的情况下, hutool 将 get 请求转换为了 post 请求


    前言

    本问题主要是来自于同事 

    情况大致如下, 同样的代码 一个是测试用例, 一个是生产环境的应用, 访问同一个第三方服务, 参数什么的完全一致 

    但是 出现的问题就是 测试用例能够拿到正确的对方的响应, 但是 生产环境的应用 却是拿到的对方的报错 

    然后 我开始以为是 是否是 签名数据存在问题, 但是 使用 curl 将两套请求[测试用例/生产环境的应用] 发送给对方服务器, 是能够拿到正确的响应的 

    所以 所有的参数 什么的都是正常的, 那么可能存在的差异的地方就是 两套发包的 jar 是否一致, 验证一下 是相同的

    另外 就是 http 客户端 是否存在问题, 然后 检查了一下 测试用例 的客户端 和 生产应用的客户端, 测试用例的是 hutool-all-5.8.6, 生产应用的是 hutool-all-5.4.0

    然后 二话不说 在开发机上面写了一个 case 来发送请求到对方服务器 

    然后 使用不同的 hutool-all 的包, 然后 果然 问题复现了

    然后 之后抓包看了一下 两个版本发送的请求, 原来 是 hutool-5.4.0 将我的 get 请求改成了 post 请求, 然后 导致对方服务响应异常

    这里 大概是根据 实际的问题情况 复现一下 这一整套情况

     

     

    测试用例

    代码使用如下相同的代码, 测试的时候 切换 hutool-all 的依赖的版本 

    1. package com.hx.test05;
    2. import cn.hutool.http.HttpRequest;
    3. import cn.hutool.http.HttpResponse;
    4. import cn.hutool.http.HttpUtil;
    5. import cn.hutool.http.Method;
    6. import com.alibaba.fastjson.JSON;
    7. import java.util.LinkedHashMap;
    8. import java.util.Map;
    9. /**
    10. * Test16PostHutoolRequest
    11. *
    12. * @author Jerry.X.He
    13. * @version 1.0
    14. * @date 2023/2/19 15:22
    15. */
    16. public class Test16PostHutoolRequest {
    17. // Test16PostHutoolRequest
    18. public static void main(String[] args) {
    19. String url = "http://localhost:8291/userHome/serviceStats";
    20. HttpRequest request = HttpUtil.createRequest(Method.GET, url);
    21. Map<String, String> params = new LinkedHashMap<>();
    22. params.put("pageNo", "1");
    23. request.body(JSON.toJSONString(params));
    24. Map<String, String> headers = new LinkedHashMap<>();
    25. headers.put("Content-Type", "application/json;charset=UTF-8");
    26. headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36");
    27. headers.put("Accept", "application/json, text/plain, */*");
    28. request.addHeaders(headers);
    29. HttpResponse response = request.execute();
    30. System.out.println(response.body());
    31. int x = 0;
    32. }
    33. }

     

    服务端代码大致如下 

    主要的处理就是针对 “/serviceStats” 的 get, post 做出不同的处理, 以方便观察 

    1. @Operation(summary = "服务统计查询")
    2. @GetMapping("/serviceStats")
    3. @ResponseStatus(HttpStatus.OK)
    4. public ResponseData<JSONObject> serviceStats() {
    5. JSONObject result = new JSONObject();
    6. result.put("availableServiceCount", 5);
    7. result.put("unavailableServiceCount", 5);
    8. return super.ok(result);
    9. }
    10. @Operation(summary = "服务统计查询")
    11. @PostMapping("/serviceStats")
    12. @ResponseStatus(HttpStatus.OK)
    13. public ResponseData<UserHomeServiceStatusView> serviceStats2() {
    14. throw new RuntimeException("服务器异常");
    15. }

     

     

    在高版本的 hutool-all 5.7.4 请求的结果如下 

    250483259fdb44919c635485d34df031.png

     

    在 hutool-all 5.4.0 请求的结果如下, 可以看到的是 发送的 GET 请求, 走的是 POST 的处理 

    9b98d7bf45a945f6a8e236c0cd234483.png

     

     

    问题抓包分析

    在 hutool-all-5.7.4 版本中抓包 发送的请求如下, 发现 代码中发送的 GET 请求, 实际上发的包是 GET请求 

    fe65beee74fb4c9aa67cfb9fdd48ab9b.png

     

    在 hutool-all-5.4.0 版本中抓包 发送的请求如下, 发现 代码中发送的 GET 请求, 实际上发的包是 POST 请求 

    5370b0cbb70f4e70aea25b39742b0222.png

     

     

    问题代码分析 

    将 get 换成 post 的地方居然是在 jdk 的 HttpUrlConnection 里面 

    只要是使用了 HttpUrlConnection.getOutputStream 的 get 请求, 都会被换成 post 请求 

    7703adef59634f929f2749b76eb105bc.png

     

    HttpConnection.getOutputStream 的处理方式如下, 直接 获取 HttpURLConnection 的 outputStream

    b6eae91ab3054317a235ddd9ddb0df19.png

     

    然后我们来看一下 hutool-5.7.4 中的处理方式 

    这里对 这里场景做了 特殊的处理

    80ae0903446b411aa6b2ee77ca7d9a18.png

     

     

    这个问题的修复在 5.4.2 版本中修复的 

    Change Log 参见 CHANGELOG_5.0-5.7

    74afcb65709c4dd59ad898d404e4b388.png

     

    具体的调整来自于这里 commitLog 

    17fc24ed37604ba1bd47c586d74b03d7.png

     

     

     

     

     

  • 相关阅读:
    【深入浅出玩转FPGA学习5-----复位设计】
    Docker从入门到进阶之进阶操作(3) —— 使用 supermin5来构建镜像
    C语言内功修炼【整型在内存中的存储】
    Vue的详细知识点梳理
    php代码审计之——phpstorm动态调试
    dreamweaver动漫HTML网站制作——海贼王主题网页1页海贼王我当定了(HTML+CSS)
    Mac(M1)安装mysqlclient失败解决办法-error: subprocess-exited-with-error
    彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-用户系统EP03
    Java无锁并发
    网络安全-黑客技术-小白学习
  • 原文地址:https://blog.csdn.net/u011039332/article/details/129115062