V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
RedBeanIce
V2EX  ›  Java

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

  •  
  •   RedBeanIce · 2023-10-24 17:47:46 +08:00 · 1009 次点击
    这是一个创建于 396 天前的主题,其中的信息可能已经有所发展或是发生改变。
    (由于请求 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 18:09:20 +08:00
    http 状态码 400 很明显了,你的请求入参不对。
    RedBeanIce
        2
    RedBeanIce  
    OP
       2023-10-24 18:11:09 +08:00
    @lsk569937453

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

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

    贴一下获取代码吧
    RedBeanIce
        5
    RedBeanIce  
    OP
       2023-10-24 19:08:44 +08:00
    @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 19:16:23 +08:00
    @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 20:00:40 +08:00 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 20:14:10 +08:00   ❤️ 1
    OP 写代码时首先要明白自己要什么。
    你现在要的是那段报错 json OK
    那么 httpclient 你请求时就要返回一个 response ,然后判断 http code ,400 就取 response 的内容,那就是你要的东西。至于是哪个 api 可以自行查找

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

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

    最开始的时候,result 的处理在下面,,现在挪到上面去就好了,
    xiaokongwu
        14
    xiaokongwu  
       2023-10-25 13:48:48 +08:00   ❤️ 1
    @RedBeanIce 嗯,那就是 stream 读取的事,可能之前的代码在前面有 read 操作,导致 IOUtils 读不到
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2734 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 71ms · UTC 14:54 · PVG 22:54 · LAX 06:54 · JFK 09:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.