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

198 天前
 RedBeanIce
(由于请求 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 。


问题:如开头
852 次点击
所在节点    Java
14 条回复
lsk569937453
198 天前
http 状态码 400 很明显了,你的请求入参不对。
RedBeanIce
198 天前
@lsk569937453

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

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

贴一下获取代码吧
RedBeanIce
198 天前
@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
198 天前
@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
198 天前
@RedBeanIce
String personResultAsJsonStr = null;
try {
personResultAsJsonStr = restTemplate.postForObject(url, request, String.class);

catch (HttpStatusCodeException e) {
//你要的响应体
System.out.println(e.getResponseBodyAsString());
}
ZZ74
198 天前
OP 写代码时首先要明白自己要什么。
你现在要的是那段报错 json OK
那么 httpclient 你请求时就要返回一个 response ,然后判断 http code ,400 就取 response 的内容,那就是你要的东西。至于是哪个 api 可以自行查找

resttemplate 没用过 楼上的应该就行。
0xsui
197 天前
最简单方法就是用 postman ,在浏览器里调试获取到登录的连接和所有请求参数,复制粘贴到 postman ,发起请求调试没问题了,直接在 postman 里面生成 java 代码,复制代码到开发工具,运行就行了,这些网络请求代码完全不用自己写。
RedBeanIce
197 天前
@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
197 天前
@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
197 天前
OP 的意思应该是,status 400 时,`result = IOUtils.toString(instream, StandardCharsets.UTF_8);`获取不到内容
RedBeanIce
197 天前
@xiaokongwu

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

最开始的时候,result 的处理在下面,,现在挪到上面去就好了,
xiaokongwu
197 天前
@RedBeanIce 嗯,那就是 stream 读取的事,可能之前的代码在前面有 read 操作,导致 IOUtils 读不到

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/985000

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX