Sending multipart requests using Spring Boot with specific header for every part - spring-boot

Postman request
As mentioned in image I would like to send content-type as application/json for a particular part of a multipart request in springboot application.

use MultipartBodyBuilder to build your request.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("add custome header", "header value");
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("json_part", "").header("Content-Type", "application/json");
MultiValueMap<String, HttpEntity<?>> body = builder.build();
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(body,
headers);
RestTemplate restTemplate = new RestTemplateBuilder().build();
ResponseEntity<String> postResponse = restTemplate
.postForEntity("yoururl", requestEntity, String.class);

Related

How can Spring RestTemplate deal with response content-type "text/csv; charset=utf-8-sig" sent by a third party service?

With RestTemplate, I post a request to a third party service whose response content-type is text/csv; charset=utf-8-sig
When parsing the response, Spring rejects it with the following message :
Invalid mime type "text/csv; charset=utf-8-sig": unsupported charset 'utf-8-sig'
I don't know what utf-8-sig means, but I have no other choices but adapt to the third party service.
Below is the code I use :
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition contentDisposition = ContentDisposition
.builder("form-data").name("data")
.filename(fichierInput.get().getName()).build();
fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
HttpEntity<byte[]> fileEntity =
new HttpEntity<>(content.getBytes(), fileMap);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("data", fileEntity);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
try {
ResponseEntity<byte[]> response = restTemplate
.exchange(this.applicationProperties.getGeoloc().getUrl(),
HttpMethod.POST, requestEntity, byte[].class);
log.debug("retour de geoloc : {} ", response.getBody());
} catch (HttpClientErrorException e) {
e.printStackTrace();
}
My question is : Do I have a way to tell Spring not to read this header but instead take the request body "as-is" ?
Thanks for your help!
I ended up by creating a custom interceptor to modify the headers of the response => example here
Added this in the header:
headerMap.put(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
Also make sure you have latest jackson core included, If you are using gradle use:
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.0.rc1'

Spring RestTemplate exchange return 204 and in postman 200

I'm turning around since this morning , i've this method that return NO_CONTENT (204) in Java, but when i execute the same URL in postman i got Content (200)
String encodedCredentials = getEncodedCredentials(deviceConfigurationInstance);
RestTemplate restTemplate = getRestTemplate(url, deviceConfigurationInstance);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + encodedCredentials);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", "*/*");
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, request, retType);
return response;
I've add the credential in postman also
What i've forgot in Java ?
Note : retType has Class<T> as type

Spring Boot Upload file via PUT

I have a curl query:
curl -v -X PUT --upload-file "test.txt" http://remote_api_service/api/files
I have a Spring Boot application and my goal is to write a query that reflects the curl I posted above. How can I do that with RestTemplate or WebClient?
You need to create HttpEntity with header and body. Set the content-type header value to MediaType.MULTIPART_FORM_DATA.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", new FileSystemResource("test.txt"));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://remote_api_service/api/files";
RestTemplate restTemplate = new RestTemplate();
restTemplate.put(serverUrl, requestEntity);

How to not escape form body characters in Spring RestTemplate when making a POST request?

I have following code where I am making a POST form request. The request body contains username and password. Password contains # characters, which is replaced by RestTemplate with %40 and I am getting "unauthorized" error as the password is wrong now.
Following is the debug info from bufferOutput(request body)
merchant_id=firstname+de-lastname%40gmail.com&password=%40Password
Here is the code snippet that is making the call.
MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
String url = "SOME_URL";
formData.add("username", "xay#gmail.com");
formData.add("password", "#name321");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<MultiValueMap<String,String>>(formData,headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
restTemplate.exchange(url, HttpMethod.POST, requestEntity, Authentication.class,"321");
The question is how to tell restTemplate not to escape body data ?
Note that the request has to be a post form request and I can not use UriComponentsBuilder to fix the problem.
I think you need to add a FormHttpMessageConverter to your RestTemplate rather than a StringHttpMessageConverter.

Spring RestTemplate redirect 302

I'm trying to use spring rest template to do a post request to login in.
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
LinkedMultiValueMap<String, Object> mvm = new LinkedMultiValueMap<String, Object>();
mvm.add("LoginForm_Login", "login");
mvm.add("LoginForm_Password", "password");
ResponseEntity<String> result = restTemplate.exchange(uriDWLogin, HttpMethod.POST, requestEntity, String.class);
My ResponseEntity status is 302, i want to follow this request to get the body response , because i didn't get the body for this request.
18:59:59.170 MAIN [http-nio-8080-exec-83] DEBUG c.d.s.c.DemandwareCtlr - loginToSandbox - StatusResponse - 302
18:59:59.170 MAIN [http-nio-8080-exec-83] DEBUG c.d.s.c.DemandwareCtlr - loginToSandbox - BodyResponse -
What can I do to solve this problem ?!
The redirection is followed automatically if the request is a GET request (see this answer). To make it happen on POST requests, one option might be to use a different request factory, like HttpComponentsClientHttpRequestFactory, and set it to use an HttpClient with the required settings to follow the redirect (see LaxRedirectStrategy):
final RestTemplate restTemplate = new RestTemplate();
final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
final HttpClient httpClient = HttpClientBuilder.create()
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
factory.setHttpClient(httpClient);
restTemplate.setRequestFactory(factory);
I haven't tested, but this should work.

Resources