I'm trying to implement the equivalent of the following cURL command in Spring, to call an API (Twilio) to upload a media :
curl --header 'Authorization: Basic <VALID_BASIC_AUTH_TOKEN>' --data-binary "@test.png" https://mcs.us1.twilio.com/v1/Services/<ACCOUNT_ID>/Media -v
This request works perfectly, and the headers generated are :
> Accept: */*
> Authorization: Basic <VALID_BASIC_AUTH_TOKEN>
> Content-Length: 385884
> Content-Type: application/x-www-form-urlencoded
My code in java is :
@Repository
public class TwilioMediaRepository {
    private RestTemplate client;
    @Value("${twilio.chat.sid}")
    private String chatSid;
    @Value("${twilio.media.api.endpoint}")
    private String endpoint;
    @Value("${twilio.all.accountsid}")
    private String accountSid;
    @Value("${twilio.all.authtoken}")
    private String accountSecret;
    @Autowired
    public TwilioMediaRepository(RestTemplate client) {
        this.client = client;
    }
    public Media postMedia(byte[] file) {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.ALL));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        client.getInterceptors().add(new RequestResponseLoggingInterceptor());
        client.getInterceptors().add(new BasicAuthorizationInterceptor(accountSid, accountSecret));
        HttpEntity<byte[]> entity = new HttpEntity<>(file, headers);
        ResponseEntity<Media> media = this.client.postForEntity(generateUrl(), entity, Media.class);
        return media.getBody();
    }
    private String generateUrl() {
        return String.format(endpoint, chatSid);
    }
}
The log of the request show that the headers are exactly the same as the cURL request :
URI         : https://mcs.us1.twilio.com/v1/Services/<ACCOUNT_ID>/Media
Method      : POST
Headers     : {Accept=[*/*], Content-Type=[application/x-www-form-urlencoded], Content-Length=[385884], Authorization=[Basic <VALID_BASIC_AUTH_TOKEN>]}
Request body: <bunch of unreadable bytes>
But the log of the response shows that my request is not valid for Twilio :
Status code  : 400
Status text  : Bad Request
Headers      : {Content-Type=[text/html], Date=[Wed, 08 Aug 2018 15:32:50 GMT], Server=[nginx], X-Shenanigans=[none], Content-Length=[166], Connection=[keep-alive]}
Response body: <html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
How are we supposed to send a binary file to comply with the --data-binary property of cURL in Spring ? 
I tried to send HttpEntity<ByteArrayResource>, HttpEntity<byte[]>, HttpEntity<FileSystemResource>, HttpEntity<ClassPathResource> but without any success. 
Note : This API doesn't support multipart file upload.
Problem solved. Contrarily to what the cURL log show, the API I use doesn't want a application/x-www-form-urlencoded content-type.
Using the file content-type solve the issue (in my case image/png)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With