1

Using Spring RestTemplate, buffer request body set to false and empty body

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
requestFactory.setConnectTimeout(60_000);
RestTemplate restTemplate = RestTemplate(requestFactory);
restTemplate.exchange(uri, HttpMethod.PUT, new HttpEntity<>(httpHeaders), Void.class);

I receive 411 - Length Required status code in response. For some reason Spring RestTemplate does not put Content-Length: 0 header on the request.

In case I comment requestFactory.setBufferRequestBody(false); line, it works perfect. But I need it for sending large files.

UPD: Looking into debug logs showed us, that request doesn't contain Content-Length header.

Michal Foksa
  • 11,225
  • 9
  • 50
  • 68
dmitryvim
  • 1,983
  • 4
  • 15
  • 27
  • Can you please add values of parameters to `restTemplate.exchange` call? – Michal Foksa Jun 27 '16 at 14:53
  • Update to HttpMethod.PUT. But other parametres are not significant. uri - some rackspace service uri, httpHeaders are single authorization token. – dmitryvim Jun 28 '16 at 09:20
  • The problem is, that request hasn't header Content-Length in it. Checked it with debug resttemplate logging. – dmitryvim Jun 28 '16 at 09:22
  • I am most interested in how you read and send file. – Michal Foksa Jun 28 '16 at 09:35
  • Maybe http client uses `chunked encoding`: https://en.wikipedia.org/wiki/Chunked_transfer_encoding . What is size of a file you send? – Michal Foksa Jun 28 '16 at 10:10
  • the problem, I try to send big file and empty request via the same restTemplate. With notnull request everything is ok, put this unbuf resttemplate unable to send empty put request – dmitryvim Jun 28 '16 at 12:05
  • Did you try RestTemplate with different http client? Like Apache HTTP? – Michal Foksa Jun 28 '16 at 12:39
  • As result I use two different restTemplate for two types of operations (for large files not buffered, and buffered for others) – dmitryvim Sep 23 '16 at 13:35
  • Makes sense. Anyway I managed to replicate the issue that time and found Apache http client does not have it. See my answer bellow. – Michal Foksa Sep 23 '16 at 13:53

2 Answers2

1

I managed to replicate your issue with RestTemplate and SimpleClientHttpRequestFactory. After switching to Apache HttpComponents HttpClient the issue is gone.

Here you are how I configured RestTemplate:

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

CloseableHttpClient httpClient = HttpClientBuilder
    .create()
    .build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setBufferRequestBody(false);

RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.exchange(......);

Hope it helps.

Michal Foksa
  • 11,225
  • 9
  • 50
  • 68
0

I have the same problem. I haven't solved it with RestTemplate. I solved it in such way:

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("you_url");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
FileBody fileBody = new FileBody(tempFile.toFile(), ContentType.MULTIPART_FORM_DATA, "file_name");
        builder.addPart("parameter_name", fileBody);
        HttpEntity multipart = builder.build();
        uploadFile.setEntity(multipart);

        try (CloseableHttpResponse response = httpClient.execute(uploadFile)) {
            //....
        }