Skip to content

Commit

Permalink
chore: Region set and encode query params (#755)
Browse files Browse the repository at this point in the history
* chore: fix error response and rest client

* Set region and Encode Query params
  • Loading branch information
sbansla committed Jun 25, 2024
1 parent 519d5a9 commit 99c4d98
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 33 deletions.
10 changes: 8 additions & 2 deletions src/main/java/com/sendgrid/ApiKeySendGrid.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sendgrid;

import com.sendgrid.constant.EnumConstants;
import com.sendgrid.constant.ErrorMessages;
import com.sendgrid.exception.AuthenticationException;
import com.sendgrid.http.ApiKeyRestClient;
Expand Down Expand Up @@ -39,6 +40,9 @@ public static synchronized void setRegion(final String region) {
if (region == null || region.isEmpty()) {
throw new AuthenticationException(String.format(ErrorMessages.EMPTY_STRING, "REGION"));
}
if (!EnumConstants.Region.getValues().contains(region)) {
throw new AuthenticationException(String.format(ErrorMessages.INVALID_STRING, "REGION"));
}
if (!Objects.equals(region, ApiKeySendGrid.region)) {
ApiKeySendGrid.invalidate();
}
Expand Down Expand Up @@ -77,8 +81,10 @@ private static ApiKeyRestClient buildRestClient() {
if (userAgentExtensions != null) {
builder.userAgentExtensions(ApiKeySendGrid.userAgentExtensions);
}
// TODO: Check if it mandatory to fetch region from customer.
builder.region(region);
if (region == null)
builder.region(EnumConstants.Region.GLOBAL.getValue());
else
builder.region(region);
return builder.build();
}

Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/sendgrid/constant/Domains.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.sendgrid.constant;

public enum Domains {
API("api");
private final String value;

private Domains(final String value) {
this.value = value;
}

public String toString() {
return value;
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/sendgrid/constant/EnumConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class EnumConstants {
@Getter
@RequiredArgsConstructor
Expand All @@ -12,4 +16,19 @@ public enum ContentType {

private final String value;
}

@Getter
@RequiredArgsConstructor
public enum Region {
GLOBAL("global"),
EU("eu");

private final String value;

public static List<String> getValues() {
return Arrays.stream(Region.values())
.map(Region::getValue)
.collect(Collectors.toList());
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/sendgrid/constant/ErrorMessages.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
@UtilityClass
public class ErrorMessages {
public static final String EMPTY_STRING = "'%s' can not be null or empty";

public static final String INVALID_STRING = "'%s' is invalid";
public static final String DEFAULT_REST_CLIENT = "Sending API request using default '%s' RestClient";
}
65 changes: 65 additions & 0 deletions src/main/java/com/sendgrid/exception/GenericApiError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.sendgrid.exception;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.List;
import java.util.StringJoiner;

@ToString
public class GenericApiError {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("errors")
@Getter
@Setter
private List<GenericError> errors;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("id")
@Getter
@Setter
private String id;

public GenericApiError() {
}

private GenericApiError(GenericApiError.Builder builder) {
this.errors = builder.errors;
this.id = builder.id;
}

// Builder class for constructing object
public static class Builder {
private List<GenericError> errors;
private String id;

public Builder() {
}

public GenericApiError.Builder errors(List<GenericError> errors) {
this.errors = errors;
return this;
}

public GenericApiError.Builder id(String id) {
this.id = id;
return this;
}

public GenericApiError build() {
return new GenericApiError(this);
}

}

@Override
public String toString() {
StringJoiner joiner = new StringJoiner(", ", GenericApiError.class.getSimpleName() + "(", ")");
if (errors != null) joiner.add("errors=" + errors);
if (id != null) joiner.add("id=" + id);
return joiner.toString();
}

}
78 changes: 78 additions & 0 deletions src/main/java/com/sendgrid/exception/GenericError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.sendgrid.exception;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.StringJoiner;

@ToString
public class GenericError {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("message")
@Getter
@Setter
private String message;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("field")
@Getter
@Setter
private String field;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("help")
@Getter
@Setter
private Object help;

public GenericError() {
}

private GenericError(GenericError.Builder builder) {
this.message = builder.message;
this.field = builder.field;
this.help = builder.help;
}

// Builder class for constructing object
public static class Builder {
private String message;
private String field;
private Object help;

public Builder() {
}

public GenericError.Builder message(String message) {
this.message = message;
return this;
}

public GenericError.Builder field(String field) {
this.field = field;
return this;
}

public GenericError.Builder help(Object help) {
this.help = help;
return this;
}

public GenericError build() {
return new GenericError(this);
}

}

@Override
public String toString() {
StringJoiner joiner = new StringJoiner(", ", GenericError.class.getSimpleName() + "(", ")");
if (message != null) joiner.add("message=" + message);
if (field != null) joiner.add("field=" + field);
if (help != null) joiner.add("help=" + help);
return joiner.toString();
}

}

1 change: 1 addition & 0 deletions src/main/java/com/sendgrid/http/ApiKeyRestClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

public class ApiKeyRestClient {
private final String apiKey;
@Getter
private final String region;
@Getter
private final ObjectMapper objectMapper;
Expand Down
31 changes: 21 additions & 10 deletions src/main/java/com/sendgrid/http/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class Request {
@Getter
private final String url;
@Getter
private final String domain;
@Getter
private String body;
@Getter
private Map<String, String> headers;
Expand All @@ -33,26 +35,31 @@ public void addHeader(String key, String value) {

private Request(Builder builder) {
this.method = builder.method;
this.domain = builder.domain;
this.region = builder.region;
this.body = builder.body;
this.headers = builder.headers;

String baseUrl = builder.url;
String baseUrl = Utility.buildBaseUrl(domain, region, builder.endPoint);
baseUrl = Utility.buildWithPathParams(baseUrl, builder.pathParams);
baseUrl = Utility.buildWithQueryParams(baseUrl, builder.queryParams);
this.url = baseUrl;
}

public static class Builder {
private String url;
private String endPoint;
private HttpMethod method;
private String domain;
private String region;
private Map<String, String> headers = new HashMap<>();
private Map<String, List<String>> queryParams = new HashMap<>();
private Map<String, String> queryParams = new HashMap<>();
private Map<String, String> pathParams = new HashMap<>();
private String body;

public Builder(HttpMethod method, String url) {
public Builder(HttpMethod method, String endPoint, String domain) {
this.method = method;
this.url = url;
this.endPoint = endPoint;
this.domain = domain;
}

public Builder addPathParam(String key, String value) {
Expand All @@ -70,23 +77,27 @@ public Builder addHeaderParam(String key, String value) {
* limit: If limit occurs as query param in open api spec
* offset: If offset occurs as query param in open api spec
* query: If there is query parameter apart from limit and offset.
* It will be the responsibility of the client to build a compound query, encode it and pass it as a query parameter in the query field.
* It will be the responsibility of the client to build a compound query and pass it as a query parameter in the query field.
*/
public Builder addQueryParam(String key, String value) {
if (!queryParams.containsKey(key)) {
queryParams.put(key, new ArrayList<String>());
}
queryParams.get(key).add(value);
queryParams.put(key, value);
return this;
}

public Builder addBody(String body) {
this.body = body;
return this;
}

public Builder region(String region) {
this.region = region;
return this;
}

public Request build() {
return new Request(this);
}
}


}
55 changes: 34 additions & 21 deletions src/main/java/com/sendgrid/util/Utility.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
package com.sendgrid.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sendgrid.exception.ApiConnectionException;
import com.sendgrid.exception.ApiException;
import com.sendgrid.constant.EnumConstants;
import org.apache.http.client.utils.URIBuilder;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

public class Utility {
public static String buildWithPathParams(String path, Map<String, String> params) {

public static String buildBaseUrl(final String domain, final String region, final String endPoint) {
List<String> availableRegions = EnumConstants.Region.getValues();
StringBuilder defaultDomain = new StringBuilder(domain);
if (availableRegions.contains(region)) {
if (!EnumConstants.Region.GLOBAL.getValue().equals(region)) {
defaultDomain.append(".");
defaultDomain.append(region);
}
}
return "https://" + defaultDomain.toString() + ".sendgrid.com" + endPoint;
}
public static String buildWithPathParams(String path, final Map<String, String> params) {
for (Map.Entry<String, String> entry : params.entrySet()) {
String placeholder = "\\{" + entry.getKey() + "\\}";
path = path.replaceAll(placeholder, entry.getValue());
}
return path;
}

public static String buildWithQueryParams(String path, Map<String, List<String>> queryParams) {
if (queryParams.isEmpty()) {
return path;
public static String buildWithQueryParams(String path, final Map<String, String> queryParams) {
URIBuilder builder = new URIBuilder();
if (queryParams != null) {
String multiValueDelimiter = "&";
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();

if (value.contains(multiValueDelimiter)) {
List<String> values = Arrays.asList(value.split(multiValueDelimiter));
for (String val : values) {
builder.addParameter(key, val);
}
} else {
builder.setParameter(key, value);
}
}
}
StringJoiner joiner = new StringJoiner("&");
queryParams.forEach((key, values) -> {
values.forEach(value -> {
joiner.add(key + "=" + value); // In case all query parameter needs to be URL Encoded, encode value here.
});
});
path = path + "?" + joiner.toString();
return path;
return path + builder.toString();
}
}

0 comments on commit 99c4d98

Please sign in to comment.