Java 防止弹簧';通过为多部分/表单数据中的每个参数添加标题来恢复RestTemplate
我必须使用Spring的Java 防止弹簧';通过为多部分/表单数据中的每个参数添加标题来恢复RestTemplate,java,spring,http-headers,multipartform-data,resttemplate,Java,Spring,Http Headers,Multipartform Data,Resttemplate,我必须使用Spring的RestTemplate来调用一个外部API,该API使用内容类型:multipart/form data接收POST请求。输入数据只是键值,没有附件,但服务器强制我使用多部分/表单数据 以下是工作正常的原始请求 POST http://the-api:8080 HTTP/1.1 Content-Type: multipart/form-data; boundary=--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL Accept: */* Hos
RestTemplate
来调用一个外部API,该API使用内容类型:multipart/form data
接收POST请求。输入数据只是键值,没有附件,但服务器强制我使用多部分/表单数据
以下是工作正常的原始请求
POST http://the-api:8080 HTTP/1.1
Content-Type: multipart/form-data; boundary=--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Accept: */*
Host: the-api:8080
accept-encoding: gzip, deflate
content-length: 680
Connection: keep-alive
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param1"
value1
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param2"
value2
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL--
下面是我从RestTemplate的日志中提取并重新排列的原始请求,它不起作用,因为服务器将头误认为值
POST http://the-api:8080 HTTP/1.1
Content-Type: multipart/form-data; boundary=--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Accept: */*
Host: the-api:8080
accept-encoding: gzip, deflate
content-length: 680
Connection: keep-alive
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param1"
Content-Type: text/plain;charset=UTF-8
Content-Length: 29
value1
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param2"
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
value2
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL--
下面是代码
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("param1", "value1);
params.add("param2", "value2);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
URI uri = UriComponentsBuilder.fromHttpUrl("http://the-api:8080")
.build().encode(Charset.forName("UTF-8")).toUri();
return restTemplate.postForObject(uri, request, KKPMailResponse.class);
HttpHeaders=newhttpheaders();
headers.setContentType(MediaType.MULTIPART\u FORM\u DATA);
多值映射参数=新的LinkedMultiValueMap();
参数添加(“参数1”、“值1”);
参数添加(“参数2”、“值2”);
HttpEntity请求=新的HttpEntity(参数、头);
URI=UriComponentsBuilder.fromHttpUrl(“http://the-api:8080")
.build().encode(Charset.forName(“UTF-8”)).toUri();
返回restemplate.postForObject(uri、请求、KKPMailResponse.class);
问题:
如何防止Spring的RestTemplate自动添加标题
内容类型:text/plain;charset=UTF-8
和内容长度:xx
对于每个参数如果您认为可以使用ClientHttpRequestInterceptor删除标题:
public class SomeHttpRequestInterceptor implements ClientHttpRequestInterceptor
{
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
{
HttpHeaders headers = request.getHeaders();
headers.remove("your header 1);
headers.remove("your header 2);
return execution.execute(request, body);
}
}
并在RestTemplate中按以下方式设置:
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = Arrays.asList(new CustomHttpRequestInterceptor())
restTemplate.setInterceptors(interceptors);
RestTemplate RestTemplate=new RestTemplate();
List interceptors=Arrays.asList(新的CustomHttpRequestInterceptor())
restTemplate.setInterceptors(拦截器);
我没有找到阻止Spring生成条目的方法,但是您可以在发送请求之前使用拦截器删除它们。为此,您必须在拦截器中操作请求主体,如下所示:
public class MultiPartFormDataCleaningInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
final MediaType contentType = request.getHeaders().getContentType();
if (contentType != null
&& MediaType.MULTIPART_FORM_DATA.getType().equals(contentType.getType())
&& MediaType.MULTIPART_FORM_DATA.getSubtype().equals(contentType.getSubtype())) {
return execution.execute(request, stripContentTypeAndLength(body));
}
return execution.execute(request, body);
}
private byte[] stripContentTypeAndLength(byte[] body) {
final String bodyStr = new String(body);
final StringBuilder builder = new StringBuilder();
try (final Scanner scanner = new Scanner(bodyStr)) {
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
if (!line.startsWith("Content-Type:")
&& !line.startsWith("Content-Length:")) {
builder.append(line).append("\r\n");
}
}
}
final String newBodyStr = builder.toString();
return newBodyStr.getBytes();
}
}
不幸的是,这会删除请求的主标头,而不是每个参数的主体中的标头。另一个问题是头是不可变映射,remove()方法将引发异常。