diff --git a/pom.xml b/pom.xml
index 8e95f10179..d6bded8b85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -269,6 +269,12 @@
4.13.2
test
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.13
+ test
+
com.tngtech.archunit
archunit
diff --git a/src/main/java/com/twilio/constant/EnumConstants.java b/src/main/java/com/twilio/constant/EnumConstants.java
index 7d2f70b590..3d310e203d 100644
--- a/src/main/java/com/twilio/constant/EnumConstants.java
+++ b/src/main/java/com/twilio/constant/EnumConstants.java
@@ -9,7 +9,8 @@ public class EnumConstants {
@RequiredArgsConstructor
public enum ContentType {
JSON("application/json"),
- FORM_URLENCODED("application/x-www-form-urlencoded");
+ FORM_URLENCODED("application/x-www-form-urlencoded"),
+ MULTIPART_FORM_DATA("multipart/form-data");
private final String value;
}
diff --git a/src/test/java/com/twilio/ClusterTest.java b/src/test/java/com/twilio/ClusterTest.java
index a4dc2e5337..9c41bc4ed5 100644
--- a/src/test/java/com/twilio/ClusterTest.java
+++ b/src/test/java/com/twilio/ClusterTest.java
@@ -1,7 +1,9 @@
package com.twilio;
import com.twilio.base.Page;
-
+import com.twilio.base.bearertoken.ResourceSet;
+import com.twilio.http.CustomHttpClient;
+import com.twilio.http.TwilioRestClient;
import com.twilio.rest.api.v2010.account.IncomingPhoneNumber;
import com.twilio.rest.api.v2010.account.IncomingPhoneNumberReader;
import com.twilio.rest.api.v2010.account.Message;
@@ -9,6 +11,7 @@
import com.twilio.rest.chat.v2.service.User;
import com.twilio.rest.events.v1.Sink;
import com.twilio.rest.events.v1.Subscription;
+import com.twilio.rest.previewiam.organizations.Account;
import org.hamcrest.CoreMatchers;
import org.junit.Assume;
import org.junit.Before;
@@ -19,10 +22,9 @@
import java.util.List;
import java.util.Map;
-import static org.junit.Assert.*;
-
-import com.twilio.rest.previewiam.organizations.Account;
-import com.twilio.base.bearertoken.ResourceSet;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
public class ClusterTest {
String fromNumber;
@@ -32,6 +34,8 @@ public class ClusterTest {
String clientSecret;
String organisationSid;
+ TwilioRestClient customRestClient;
+
@Before
public void setUp() {
// only run when ClusterTest property is passed (mvn test -Dtest="ClusterTest"), skip test run on mvn test
@@ -48,6 +52,9 @@ public void setUp() {
clientSecret = System.getenv("TWILIO_ORGS_CLIENT_SECRET");
organisationSid = System.getenv("TWILIO_ORG_SID");
TwilioOrgsTokenAuth.init(grantType, clientId, clientSecret);
+
+ // CustomHttpClient
+ customRestClient = new TwilioRestClient.Builder(apiKey, secret).accountSid(accountSid).httpClient(new CustomHttpClient()).build();
}
@Test
@@ -141,4 +148,17 @@ public void testOrgsApi(){
assertNotNull(userId);
}
+ // Test multipart/form-data
+ @Test
+ public void testMultiPartFormData() {
+ Message message = Message.creator(
+ new com.twilio.type.PhoneNumber(toNumber), new com.twilio.type.PhoneNumber(fromNumber),
+ "Where's Wallace?")
+ .create(customRestClient);
+ assertNotNull(message);
+ assertTrue(message.getBody().contains("Where's Wallace?"));
+ assertEquals(fromNumber, message.getFrom().toString());
+ assertEquals(toNumber, message.getTo().toString());
+ }
+
}
diff --git a/src/test/java/com/twilio/http/CustomHttpClient.java b/src/test/java/com/twilio/http/CustomHttpClient.java
new file mode 100644
index 0000000000..9d087555ab
--- /dev/null
+++ b/src/test/java/com/twilio/http/CustomHttpClient.java
@@ -0,0 +1,70 @@
+package com.twilio.http;
+
+import com.twilio.exception.ApiException;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.client.utils.HttpClientUtils;
+import org.apache.http.entity.BufferedHttpEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.StringBody;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+public class CustomHttpClient extends NetworkHttpClient {
+
+ public CustomHttpClient() {
+ super();
+ }
+
+ @Override
+ public Response makeRequest(T request) {
+ HttpMethod method = request.getMethod();
+ RequestBuilder builder = RequestBuilder.create(method.toString())
+ .setUri(request.constructURL().toString())
+ .setVersion(HttpVersion.HTTP_1_1)
+ .setCharset(StandardCharsets.UTF_8);
+ if (request instanceof Request) {
+ Request basicRequest = (Request) request;
+ if (basicRequest.requiresAuthentication()) {
+ builder.addHeader(HttpHeaders.AUTHORIZATION, basicRequest.getAuthString());
+ }
+ }
+
+ for (Map.Entry> entry : request.getHeaderParams().entrySet()) {
+ for (String value : entry.getValue()) {
+ builder.addHeader(entry.getKey(), value);
+ }
+ }
+ MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
+ for (Map.Entry> entry : request.getPostParams().entrySet()) {
+ for (String value : entry.getValue()) {
+ multipartEntityBuilder.addPart(entry.getKey(), new StringBody(value, ContentType.TEXT_PLAIN));
+ }
+ }
+ builder.addHeader(HttpHeaders.USER_AGENT, HttpUtility.getUserAgentString(request.getUserAgentExtensions(), true));
+ builder.setEntity(multipartEntityBuilder.build());
+ HttpResponse response = null;
+
+ try {
+ response = client.execute(builder.build());
+ HttpEntity entity = response.getEntity();
+ return new Response(
+ // Consume the entire HTTP response before returning the stream
+ entity == null ? null : new BufferedHttpEntity(entity).getContent(),
+ response.getStatusLine().getStatusCode(),
+ response.getAllHeaders()
+ );
+ } catch (IOException e) {
+ throw new ApiException(e.getMessage(), e);
+ } finally {
+ HttpClientUtils.closeQuietly(response);
+ }
+ }
+}