春季升级后,使用多部分表单数据的http调用失败

问题描述 投票:0回答:1

我们将 Spring Boot 从 3.1.11 升级到 3.3.3。升级后,当我们尝试发布 pdf 文件时,我们发现 Rest 模板存在问题。

API 调用突然失败,返回 400 BAD_REQUEST,详细信息如下 直播意外结束

http 调用具有以下标头

  1. 内容类型:多部分/表单数据
  2. 内容长度:

Http实体构建如下

  headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length));

  MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
        ByteArrayResource byteArrayResource = new ByteArrayResource(bytes,
                "Pdf name") {
            @Override
            public String getFilename() {
                return filename;
            }
        };
        parts.add("data", byteArrayResource);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

交换是在以下模板的帮助下完成的

   exchange(uri, "POST", requestEntity, String.class);

同一段代码在 Spring Boot 3.1.11 上运行良好。这样服务器端的问题就解决了。

我们看到的例外是

at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:103) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:183) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:137) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:942) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:891) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:790) ~[spring-web-6.1.12.jar:6.1.12]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:672) ~[spring-web-6.1.12.jar:6.1.12]

我们的其余模板实例是按以下方式构建的:

    SSLContext sslContext = sslContextBuilder.build();
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("****", "****");
    keyManagerFactory.init(clientStore, *****);
    sslContext.init(keyManagerFactory.getKeyManagers(), null, ****);


    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

    HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(socketFactory).build();

    CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();

    RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
为了简洁起见,

sslContextBuilder
被排除在外,并出于安全原因屏蔽了一些内容。但配置了tls协议和必要的证书。

java spring spring-boot resttemplate httpentity
1个回答
0
投票

Spring 最近似乎一直在研究如何计算内容长度。

我在 3.2.5 版本中遇到了类似的内容长度问题

尽管内容长度标头似乎具有相同的值,无论是否显式设置,但看起来服务器期望更多数据,并且客户端突然关闭了连接。

虽然我仍在进一步调查此行为,但删除显式设置内容长度标头的行解决了该问题:

headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length));
    
© www.soinside.com 2019 - 2024. All rights reserved.