Запретить RestTemplate Spring от добавления заголовка для каждого параметра в multipart / form-data - PullRequest
0 голосов
/ 19 сентября 2018

Мне нужно использовать Spring RestTemplate для вызова внешнего API, который принимает запрос POST с Content-Type: multipart/form-data.Входные данные являются только ключами-значениями, без вложений, но сервер заставляет меня использовать multipart/form-data.

Ниже приведен необработанный запрос, который отлично работает.

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);

Вопрос

Как запретить RestTemplate Spring автоматически добавлять заголовки Content-Type: text/plain;charset=UTF-8 и Content-Length: xx для каждого параметра

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Я не нашел способа запретить 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();
    }
}
0 голосов
/ 19 сентября 2018

Если вы считаете, что вы можете использовать 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...