RedBeanIce
V2EX  ›  Java

Apache HttpClient 进行 Post 请求 异常问题( Java 对接 walmart mp)

By RedBeanIce at 2023 年 10 月 24 日 · 3666 次点击
(由于请求 walmart 有账号密码,属于公司保密信息,所以无法提供实际代码)

问题:请求异常只体现在日志中,如下面的第三行日志就是日志,有体现 carrier 字段是错误的。
如果在 response 里面获取,只能获取到 bad request ,没有具体的某个字段的错误。

请问,我如何获取到日志里面的报错,然后在自己写的代码里面获取到这个报错,自己打印出来。

1 ,
```
请求框架是,Apache HttpClient

org.apache.httpcomponents
4.5.6
HttpClient
```

```
17:33:50.629 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Connection: close[\r][\n]"
17:33:50.629 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
17:33:50.629 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "{"errors":{"error":[{"code":"INVALID_REQUEST_CONTENT.GMP_ORDER_API","field":"carrier","description":"Unsupported carrier 'Fedex' was specified in line number 1. Only pre-defined names are allowed for 'carrier.' For a list of acceptable carriers, see https://developer.walmart.com/api/us/mp/orders#operation/shippingUpdates . If you select 'otherCarrier' you must also provide the tracking URL.","info":"Request content is invalid.","severity":"ERROR","category":"DATA","errorIdentifiers":{"entry":[]}}]}}"
17:33:50.629 [main] DEBUG org.apache.http.headers - http-outgoing-0 << HTTP/1.1 400 Bad Request
17:33:50.629 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Accept-Ranges: bytes

```

2 ,如果换成 resttemplate ,那么直接连日志也没有了。。response 和上述一样
我将日志等级修改 debug ,也是没有日志,只有 response 。


问题:如开头
14 条回复  •  2023-10-25 13:48:48 +08:00
lsk569937453
   1
lsk569937453  
   2023 年 10 月 24 日
http 状态码 400 很明显了,你的请求入参不对。
RedBeanIce
   2
RedBeanIce  
OP
   2023 年 10 月 24 日
@lsk569937453

请再看一下我的问题。我们问题不是 400 。

而是具体的详细的报错,仅仅体现在日志中,无法让 ta 体现在返参中。
hmmm000
   3
hmmm000  
   2023 年 10 月 24 日 via Android
resttemplate 可以通过 catch HttpStatusCodeException ,用 getResponseBodyAsString 方法获取非 200 返回的响应体。httpclient 不清楚。
xiaokongwu
   4
xiaokongwu  
   2023 年 10 月 24 日
“如果在 response 里面获取,只能获取到 bad request ,没有具体的某个字段的错误。”

贴一下获取代码吧
RedBeanIce
   5
RedBeanIce  
OP
   2023 年 10 月 24 日
@hmmm000

```
请求方式

HttpEntity<String> request = new HttpEntity<>(parse.toJSONString(), headersV2);
String personResultAsJsonStr = null;
try {
personResultAsJsonStr = restTemplate.postForObject(url, request, String.class);
} catch (RestClientException e) {
e.printStackTrace();
}
System.out.println(personResultAsJsonStr);

```

```
打印

19:05:22.927 [main] DEBUG org.springframework.web.client.RestTemplate - Created POST request for "https://marketplace.walmartapis.com/v3/orders/108829823812146/shipping"
19:05:22.928 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, application/json, application/cbor, application/*+json, */*]
19:05:22.929 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [{"orderShipment":{"orderLines":{"orderLine":[{"lineNumber":"1","orderLineStatuses":{"orderLineStatus":[{"status":"Shipped","statusQuantity":{"amount":"1","unitOfMeasurement":"EACH"},"trackingInfo":{"carrierName":{"carrier":"Fedex"},"methodCode":"Standard","shipDateTime":1698132951000,"trackingNumber":"785444130107"}}]},"sellerOrderId":"FO231024144001001"}]}}}] using [org.springframework.http.converter.StringHttpMessageConverter@7a362b6b]
19:05:23.423 [main] DEBUG org.springframework.web.client.RestTemplate - POST request for "https://marketplace.walmartapis.com/v3/orders/108829823812146/shipping" resulted in 400 (Bad Request); invoking error handler
null
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:118)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:103)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:730)

```

但是我想要的是,,

"{"errors":{"error":[{"code":"INVALID_REQUEST_CONTENT.GMP_ORDER_API","field":"carrier","description":"Unsupported carrier 'Fedex' was specified in line number 1. Only pre-defined names are allowed for 'carrier.' For a list of acceptable carriers, see https://developer.walmart.com/api/us/mp/orders#operation/shippingUpdates . If you select 'otherCarrier' you must also provide the tracking URL.","info":"Request content is invalid.","severity":"ERROR","category":"DATA","errorIdentifiers":{"entry":[]}}]}}

它提示我,,,carrier 字段有问题。。(相关描述,请看开头)
RedBeanIce
   6
RedBeanIce  
OP
   2023 年 10 月 24 日
@xiaokongwu

apache http ,,,伪代码
```
// 执行请求
CloseableHttpResponse response = httpClient.execute(post, new BasicHttpContext());
// 返回的状态 200 404 等等
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
logger.info("request url failed, http code={}, url={}", response.getStatusLine().getStatusCode(), url);
return null;
}
```
如果像是上述代码获取,,则只能获取到 bad request


报错都在日志打印里面,org.apache.http.wire ,carrier 字段有问题
hmmm000
   7
hmmm000  
   2023 年 10 月 24 日 via Android   ❤️ 1
@RedBeanIce
String personResultAsJsonStr = null;
try {
personResultAsJsonStr = restTemplate.postForObject(url, request, String.class);
} 
catch (HttpStatusCodeException e) {
//你要的响应体
System.out.println(e.getResponseBodyAsString());
}
ZZ74
   8
ZZ74  
   2023 年 10 月 24 日   ❤️ 1
OP 写代码时首先要明白自己要什么。
你现在要的是那段报错 json OK
那么 httpclient 你请求时就要返回一个 response ,然后判断 http code ,400 就取 response 的内容,那就是你要的东西。至于是哪个 api 可以自行查找

resttemplate 没用过 楼上的应该就行。
0xsui
   9
0xsui  
   2023 年 10 月 25 日   ❤️ 1
最简单方法就是用 postman ,在浏览器里调试获取到登录的连接和所有请求参数,复制粘贴到 postman ,发起请求调试没问题了,直接在 postman 里面生成 java 代码,复制代码到开发工具,运行就行了,这些网络请求代码完全不用自己写。
RedBeanIce
   10
RedBeanIce  
OP
   2023 年 10 月 25 日
@RedBeanIce

apache http ,,,伪代码
```
// 执行请求
CloseableHttpResponse response = httpClient.execute(post, new BasicHttpContext());
// 返回的状态 200 404 等等
int statusCode = response.getStatusLine().getStatusCode();
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
result = IOUtils.toString(instream, StandardCharsets.UTF_8);
}
if (statusCode != CONNCET_SUCCESS) {
logger.info("request url failed, http code={}, url={}, result={}", response.getStatusLine().getStatusCode(), url, result);
return null;
}
if (statusCode != 200) {
logger.info("request url failed, http code={}, url={}", response.getStatusLine().getStatusCode(), url);
return null;
}



```
RedBeanIce
   11
RedBeanIce  
OP
   2023 年 10 月 25 日
@RedBeanIce

apache http ,,,伪代码
```
// 执行请求
CloseableHttpResponse response = httpClient.execute(post, new BasicHttpContext());
// 返回的状态 200 404 等等
int statusCode = response.getStatusLine().getStatusCode();

HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
result = IOUtils.toString(instream, StandardCharsets.UTF_8);
}
if (statusCode != 200) {
logger.info("request url failed, http code={}, url={}, result={}", response.getStatusLine().getStatusCode(), url, result);
return null;
}


result 里面就是,成功信息,或者是异常信息

```
xiaokongwu
   12
xiaokongwu  
   2023 年 10 月 25 日
OP 的意思应该是,status 400 时,`result = IOUtils.toString(instream, StandardCharsets.UTF_8);`获取不到内容
RedBeanIce
   13
RedBeanIce  
OP
   2023 年 10 月 25 日
@xiaokongwu

hhhh ,是我让你产生误解了。很抱歉。

最开始的时候,result 的处理在下面,,现在挪到上面去就好了,
xiaokongwu
   14
xiaokongwu  
   2023 年 10 月 25 日   ❤️ 1
@RedBeanIce 嗯,那就是 stream 读取的事,可能之前的代码在前面有 read 操作,导致 IOUtils 读不到
© 2026 V2EX · 53ms · 3.9.8.5