使用java.net.HTTPClient请求返回400错误,Postman和RestTemplate正常
问题
在SpringBoot应用中,使用java.net.HTTPClient向指定URL发送JSON格式POST请求时,服务器返回400状态码,但用Postman或Spring RestTemplate发送相同请求却能得到预期响应。
我的代码
// some dummy url: String url = "http://88.22.199.111:5000/detect"; JSONObject json1 = new JSONObject(); json1.put("From", "Sawan"); json1.put("to", "Mohan"); json1.put("message", "is API working?"); json1.put("check_list", 1); HttpClient httpClient = HttpClient.newBuilder().build(); HttpRequest httpRequest = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json1.toString())) .build(); System.out.println(json1.toString()); HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); System.out.println(httpResponse.statusCode()); System.out.println(httpResponse.body());
控制台输出
{"check_list":1,"From":"Sawan","to":"Mohan","message":"is API working?"} 400 {"message": "The browser (or proxy) sent a request that this server could not understand."}
Postman对应的cURL命令
curl --location 'http://88.22.199.111:5000/detect' \ --header 'Content-Type: application/json' \ --data '{ "From":"Sawan" ,"to":"Mohan" ,"message":"is API working?" ,"check_list":1 } '
预期响应
{ "status": 200, "message": "Success", "timestamp": "2023-03-31 05:20:33.455868 +0000", "data": { "Message": "is API working?", "MessageTimeUTC": "Fri, 31 Mar 2023 05:20:33 GMT", "Message_By": "sawan", "Message_To": "mohan", "Message_Intended_For": "mohan", "Sentences": [] } }
由于实际应用中无法使用RestTemplate,需要解决HTTPClient请求报错的问题,请问代码是否存在问题?是否需要添加额外请求头?
分析与解决方案
1. 显式指定请求体编码格式
HttpRequest.BodyPublishers.ofString()默认使用UTF-8,但部分服务器需要显式确认编码。可以修改请求体构建逻辑,强制指定UTF-8编码:
.POST(HttpRequest.BodyPublishers.ofString(json1.toString(), StandardCharsets.UTF_8))
2. 添加Postman默认携带的请求头
Postman会自动添加User-Agent等请求头,部分服务器会校验这些标识信息。尝试补充User-Agent头:
HttpRequest httpRequest = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Content-Type", "application/json") .header("User-Agent", "PostmanRuntime/7.32.3") // 模拟Postman的User-Agent .POST(HttpRequest.BodyPublishers.ofString(json1.toString(), StandardCharsets.UTF_8)) .build();
3. 生成带格式的JSON字符串
Postman发送的JSON带有换行和缩进,而JSONObject.toString()生成的是紧凑格式。部分服务器对JSON格式有严格要求,可以尝试生成带缩进的JSON:
// 生成带4个空格缩进的JSON字符串 String formattedJson = json1.toString(4); .POST(HttpRequest.BodyPublishers.ofString(formattedJson, StandardCharsets.UTF_8))
4. 用字节数组发送请求体
避免字符串转字节过程中的编码问题,直接将JSON转为字节数组发送:
byte[] jsonBytes = json1.toString().getBytes(StandardCharsets.UTF_8); .POST(HttpRequest.BodyPublishers.ofByteArray(jsonBytes))
5. 对比请求详情排查差异
打印HTTPClient发送的所有请求头,和Postman的请求头做对比,找出缺失或不一致的字段:
// 打印所有请求头 httpRequest.headers().map().forEach((key, values) -> { System.out.print(key + ": "); System.out.println(String.join(", ", values)); });
内容的提问来源于stack exchange,提问作者Mohan
相关产品推荐
相关产品推荐

