Skip to content

Commit

Permalink
feat!: MVR Release Preparation (#779)
Browse files Browse the repository at this point in the history
* feat: support json content in requests (#746)

* feat: Enable json request body (#749)

* chore: added preview messaging domain url (#752)


* feat! : MVR Release Preparation
  • Loading branch information
sbansla authored Feb 9, 2024
1 parent aa5cf62 commit 6c54f01
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 32 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/test-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ jobs:
- name: Run Unit Tests
run: mvn test -B

- name: Run Cluster Test
if: (!github.event.pull_request.head.repo.fork)
env:
TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
TWILIO_API_KEY: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY}}
TWILIO_API_SECRET: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY_SECRET }}
TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
TWILIO_TO_NUMBER: ${{ secrets.TWILIO_TO_NUMBER }}
run: mvn test -DTest="ClusterTest" -B
# - name: Run Cluster Test
# if: (!github.event.pull_request.head.repo.fork)
# env:
# TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
# TWILIO_API_KEY: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY}}
# TWILIO_API_SECRET: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY_SECRET }}
# TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
# TWILIO_TO_NUMBER: ${{ secrets.TWILIO_TO_NUMBER }}
# run: mvn test -DTest="ClusterTest" -B

- name: SonarCloud Scan
if: ${{ (github.event_name == 'pull_request' || github.ref_type == 'branch') && matrix.java == 11 && !github.event.pull_request.head.repo.fork }}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ Use the following dependency in your project to grab via Maven:
<dependency>
<groupId>com.twilio.sdk</groupId>
<artifactId>twilio</artifactId>
<version>9.X.X</version>
<version>10.X.X</version>
<scope>compile</scope>
</dependency>
```

or Gradle:

```groovy
implementation "com.twilio.sdk:twilio:9.X.X"
implementation "com.twilio.sdk:twilio:10.X.X"
```

If you want to compile it yourself, here's how:
Expand Down
8 changes: 8 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

_`MAJOR` version bumps will have upgrade notes posted here._

[2024-02-08] 9.x.x to 10.x.x
### Overview

##### Twilio Java Helper Library’s major version 10.0.0 is now available. We ensured that you can upgrade to Java helper Library 10.0.0 version without any breaking changes of existing apis

Behind the scenes Java Helper is now auto-generated via OpenAPI with this release. This enables us to rapidly add new features and enhance consistency across versions and languages.
We're pleased to inform you that version 10.0.0 adds support for the application/json content type in the request body.

[2022-09-21] 8.x.x to 9.x.x
-----------------------------
### Overview
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/twilio/Domains.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public enum Domains {
IPMESSAGING("ip-messaging"),
LOOKUPS("lookups"),
MEDIA("media"),
PREVIEWMESSAGING("preview.messaging"),
MESSAGING("messaging"),
MICROVISOR("microvisor"),
MONITOR("monitor"),
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/twilio/Twilio.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ public static void setExecutorService(final ExecutorService executorService) {
}

/**
* Validate that we can connect to the new SSL certificate posted on api.twilio.com.
* Validate that we can connect to the new SSL certificate posted on tls-test.twilio.com
*
* @throws CertificateValidationException if the connection fails
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/twilio/converter/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class Converter {
* @param map map to convert
* @return converted JSON string
*/
public static String mapToJson(final Map<String, Object> map) {
public static String mapToJson(final Map<String, ? extends Object> map) {
try {
return MAPPER.writeValueAsString(map);
} catch (JsonProcessingException e) {
Expand Down
23 changes: 18 additions & 5 deletions src/main/java/com/twilio/http/NetworkHttpClient.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.twilio.http;

import com.twilio.Twilio;
import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiException;

import java.io.IOException;
Expand All @@ -19,6 +20,8 @@
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
Expand Down Expand Up @@ -129,13 +132,23 @@ public Response makeRequest(final Request request) {
}

if (method == HttpMethod.POST) {
builder.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");

for (Map.Entry<String, List<String>> entry : request.getPostParams().entrySet()) {
for (String value : entry.getValue()) {
builder.addParameter(entry.getKey(), value);
// TODO: It will be removed after one RC Release.
if (request.getContentType() == null) request.setContentType(EnumConstants.ContentType.FORM_URLENCODED);
if (EnumConstants.ContentType.JSON.getValue().equals(request.getContentType().getValue())) {
HttpEntity entity = new StringEntity(request.getBody(), ContentType.APPLICATION_JSON);
builder.setEntity(entity);
builder.addHeader(
HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.JSON.getValue());
} else {
builder.addHeader(
HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.FORM_URLENCODED.getValue());
for (Map.Entry<String, List<String>> entry : request.getPostParams().entrySet()) {
for (String value : entry.getValue()) {
builder.addParameter(entry.getKey(), value);
}
}
}

}
builder.addHeader(HttpHeaders.USER_AGENT, HttpUtility.getUserAgentString(request.getUserAgentExtensions(), isCustomClient));

Expand Down
27 changes: 18 additions & 9 deletions src/main/java/com/twilio/http/Request.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
package com.twilio.http;

import com.twilio.constant.EnumConstants;

import com.twilio.constant.EnumConstants.ContentType;
import com.twilio.exception.ApiException;
import com.twilio.exception.InvalidRequestException;

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Request {
Expand All @@ -39,7 +38,9 @@ public class Request {

private List<String> userAgentExtensions;

private ContentType contentType;
private EnumConstants.ContentType contentType;

private String body;

/**
* Create a new API request.
Expand Down Expand Up @@ -117,14 +118,22 @@ public List<String> getUserAgentExtensions() {
return this.userAgentExtensions;
}

public ContentType getContentType() {
public EnumConstants.ContentType getContentType() {
return contentType;
}

public void setContentType(ContentType contentType) {
public void setContentType(EnumConstants.ContentType contentType) {
this.contentType = contentType;
}

public String getBody() {
return body;
}

public void setBody(String body) {
this.body = body;
}

/**
* Create auth string from username and password.
*
Expand Down
23 changes: 18 additions & 5 deletions src/main/java/com/twilio/http/ValidationClient.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.twilio.http;

import com.twilio.Twilio;
import com.twilio.constant.EnumConstants;
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.config.RequestConfig;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
Expand Down Expand Up @@ -175,11 +179,20 @@ public Response makeRequest(Request request) {

HttpMethod method = request.getMethod();
if (method == HttpMethod.POST) {
builder.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");

for (Map.Entry<String, List<String>> entry : request.getPostParams().entrySet()) {
for (String value : entry.getValue()) {
builder.addParameter(entry.getKey(), value);
// TODO: It will be removed after one RC Release.
if (request.getContentType() == null) request.setContentType(EnumConstants.ContentType.FORM_URLENCODED);
if (EnumConstants.ContentType.JSON.getValue().equals(request.getContentType().getValue())) {
HttpEntity entity = new StringEntity(request.getBody(), ContentType.APPLICATION_JSON);
builder.setEntity(entity);
builder.addHeader(
HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.JSON.getValue());
} else {
builder.addHeader(
HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.FORM_URLENCODED.getValue());
for (Map.Entry<String, List<String>> entry : request.getPostParams().entrySet()) {
for (String value : entry.getValue()) {
builder.addParameter(entry.getKey(), value);
}
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/com/twilio/http/NetworkHttpClientTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.twilio.http;

import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiConnectionException;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
Expand Down Expand Up @@ -66,6 +67,7 @@ private void setup(
when(mockRequest.constructURL()).thenReturn(new URL("http://foo.com/hello"));
when(mockRequest.requiresAuthentication()).thenReturn(requiresAuthentication);
when(mockRequest.getAuthString()).thenReturn("foo:bar");
when(mockRequest.getContentType()).thenReturn(EnumConstants.ContentType.FORM_URLENCODED);
when(mockClient.execute(any())).thenReturn(mockResponse);
when(mockEntity.isRepeatable()).thenReturn(true);
when(mockEntity.getContentLength()).thenReturn(1L);
Expand Down Expand Up @@ -110,6 +112,18 @@ public void testPost() throws IOException {
assertEquals(resp.getContent(), "frobozz");
}

@Test
public void testJsonPost() throws IOException {
setup(201, "frobozz", HttpMethod.POST, false);
when(mockRequest.getContentType()).thenReturn(EnumConstants.ContentType.JSON);
String body = "{\"from\":\"+12345\",\"body\":\"message body\",\"messages\":[{\"to\":\"+12345\"}]}";
when(mockRequest.getBody()).thenReturn(body);
Response resp = client.makeRequest(mockRequest);

assertEquals(resp.getStatusCode(), 201);
assertEquals(resp.getContent(), "frobozz");
}

@Test
public void testReliableRequest() {
Request request = new Request(HttpMethod.GET, "http://foo.com/hello");
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/com/twilio/http/RequestTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.twilio.http;

import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiException;
import com.twilio.rest.Domains;
import java.time.ZonedDateTime;
Expand Down Expand Up @@ -317,4 +318,10 @@ public void testEquals() {
assertNotEquals(request, new Object());
assertNotEquals(null, request);
}
@Test
public void testContentType() {
Request r = new Request(HttpMethod.POST, "http://example.com/foobar");
r.setContentType(EnumConstants.ContentType.JSON);
assertEquals(EnumConstants.ContentType.JSON, r.getContentType());
}
}
25 changes: 25 additions & 0 deletions src/test/java/com/twilio/http/ValidationClientTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.twilio.http;

import com.twilio.constant.EnumConstants;
import org.junit.Test;

import java.security.KeyPair;
Expand All @@ -23,6 +24,7 @@ public void testHttpGet() throws Exception {
@Test
public void testHttpPost() throws Exception {
exerciseHttpMethod(HttpMethod.POST);
testContentType(HttpMethod.POST);
}

@Test
Expand All @@ -46,6 +48,29 @@ private void exerciseHttpMethod(final HttpMethod httpMethod) throws Exception {
assertNotNull(validationHeaderValue);
assertTrue(validationHeaderValue.length() > 0);
}
private void testContentType(final HttpMethod httpMethod) throws Exception {
final KeyPair keyPair = generateKeyPair();
final MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("{\n" +
" \"key1\": \"value1\",\n" +
" \"key2\": \"value2\"\n" +
"}"));
final String path = "/example123";
final HttpUrl url = server.url(path);
final ValidationClient client = new ValidationClient("dummy-sid1", "dummy-sid2", "dummy-signing-key", keyPair.getPrivate());
final Request request = new Request(httpMethod, url.url().toString());
request.setContentType(EnumConstants.ContentType.JSON);
String body = "{\"from\":\"+12345\",\"body\":\"message body\",\"messages\":[{\"to\":\"+12345\"}]}";
request.setBody(body);
final Response response = client.makeRequest(request);
assertEquals(200, response.getStatusCode());
final RecordedRequest recordedRequest = server.takeRequest();
assertEquals(httpMethod.name(), recordedRequest.getMethod());
assertEquals(EnumConstants.ContentType.JSON.getValue(), recordedRequest.getHeader("Content-Type"));
final String validationHeaderValue = recordedRequest.getHeader("Twilio-Client-Validation");
assertNotNull(validationHeaderValue);
assertTrue(validationHeaderValue.length() > 0);
}

private static KeyPair generateKeyPair() throws Exception {
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
Expand Down

0 comments on commit 6c54f01

Please sign in to comment.