Skip to content

Commit

Permalink
Issue #1109 - refactoring webrequestor execute methods
Browse files Browse the repository at this point in the history
  • Loading branch information
nbartels committed Dec 27, 2020
1 parent e75e52c commit 1523c82
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 203 deletions.
27 changes: 13 additions & 14 deletions src/main/java/com/restfb/DefaultFacebookClient.java
Expand Up @@ -23,6 +23,7 @@

import static com.restfb.logging.RestFBLogger.CLIENT_LOGGER;
import static com.restfb.util.EncodingUtils.decodeBase64;
import static com.restfb.util.ObjectUtil.requireNotEmpty;
import static com.restfb.util.ObjectUtil.verifyParameterPresence;
import static com.restfb.util.StringUtils.*;
import static com.restfb.util.UrlUtils.urlEncode;
Expand Down Expand Up @@ -271,10 +272,12 @@ public <T> Connection<T> fetchConnection(String connection, Class<T> connectionT
public <T> Connection<T> fetchConnectionPage(final String connectionPageUrl, Class<T> connectionType) {
String connectionJson;
if (!isBlank(accessToken) && !isBlank(appSecret)) {
connectionJson = makeRequestAndProcessResponse(() -> webRequestor.executeGet(String.format("%s&%s=%s",
connectionPageUrl, urlEncode(APP_SECRET_PROOF_PARAM_NAME), obtainAppSecretProof(accessToken, appSecret))));
WebRequestor.Request request = new WebRequestor.Request(String.format("%s&%s=%s", connectionPageUrl,
urlEncode(APP_SECRET_PROOF_PARAM_NAME), obtainAppSecretProof(accessToken, appSecret)), null);
connectionJson = makeRequestAndProcessResponse(() -> webRequestor.executeGet(request));
} else {
connectionJson = makeRequestAndProcessResponse(() -> webRequestor.executeGet(connectionPageUrl, getHeaderAccessToken()));
connectionJson = makeRequestAndProcessResponse(
() -> webRequestor.executeGet(new WebRequestor.Request(connectionPageUrl, getHeaderAccessToken())));
}

return new Connection<>(this, connectionJson, connectionType);
Expand Down Expand Up @@ -303,10 +306,7 @@ public FacebookClient createClientWithAccessToken(String accessToken) {
public <T> T fetchObjects(List<String> ids, Class<T> objectType, Parameter... parameters) {
verifyParameterPresence("ids", ids);
verifyParameterPresence("connectionType", objectType);

if (ids.isEmpty()) {
throw new IllegalArgumentException("The list of IDs cannot be empty.");
}
requireNotEmpty(ids, "The list of IDs cannot be empty.");

if (Stream.of(parameters).anyMatch(p -> IDS_PARAM_NAME.equals(p.name))) {
throw new IllegalArgumentException("You cannot specify the '" + IDS_PARAM_NAME + "' URL parameter yourself - "
Expand Down Expand Up @@ -405,10 +405,7 @@ public List<BatchResponse> executeBatch(List<BatchRequest> batchRequests) {
@Override
public List<BatchResponse> executeBatch(List<BatchRequest> batchRequests, List<BinaryAttachment> binaryAttachments) {
verifyParameterPresence("binaryAttachments", binaryAttachments);

if (batchRequests == null || batchRequests.isEmpty()) {
throw new IllegalArgumentException("You must specify at least one batch request.");
}
requireNotEmpty(batchRequests, "You must specify at least one batch request.");

return jsonMapper.toJavaList(
makeRequest("", true, false, binaryAttachments, Parameter.with("batch", jsonMapper.toJson(batchRequests, true))),
Expand Down Expand Up @@ -740,15 +737,17 @@ protected String makeRequest(String endpoint, final boolean executeAsPost, final
final String parameterString = toParameterString(parameters);

return makeRequestAndProcessResponse(() -> {
WebRequestor.Request request = new WebRequestor.Request(fullEndpoint, getHeaderAccessToken(), parameterString);
if (executeAsDelete && !isHttpDeleteFallback()) {
return webRequestor.executeDelete(fullEndpoint + "?" + parameterString, getHeaderAccessToken());
return webRequestor.executeDelete(request);
}

if (executeAsPost) {
return webRequestor.executePost(fullEndpoint, parameterString, binaryAttachments, getHeaderAccessToken());
request.setBinaryAttachments(binaryAttachments);
return webRequestor.executePost(request);
}

return webRequestor.executeGet(fullEndpoint + "?" + parameterString, getHeaderAccessToken());
return webRequestor.executeGet(request);
});
}

Expand Down
75 changes: 34 additions & 41 deletions src/main/java/com/restfb/DefaultWebRequestor.java
Expand Up @@ -80,37 +80,28 @@ protected enum HttpMethod {
}

@Override
public Response executeGet(String url, String headerAccessToken) throws IOException {
return execute(url, HttpMethod.GET, headerAccessToken);
public Response executeGet(Request request) throws IOException {
return execute(HttpMethod.GET, request);
}

@Override
public Response executeGet(String url) throws IOException {
return execute(url, HttpMethod.GET, null);
}
public Response executePost(Request request) throws IOException {

@Override
public Response executePost(String url, String parameters, String headerAccessToken) throws IOException {
return executePost(url, parameters, null, headerAccessToken);
}

@Override
public Response executePost(String url, String parameters, List<BinaryAttachment> binaryAttachments, String headerAccessToken)
throws IOException {

binaryAttachments = Optional.ofNullable(binaryAttachments).orElse(new ArrayList<>());
List<BinaryAttachment> binaryAttachments = request.getBinaryAttachments();

if (HTTP_LOGGER.isDebugEnabled()) {
HTTP_LOGGER.debug("Executing a POST to " + url + " with parameters "
+ (!binaryAttachments.isEmpty() ? "" : "(sent in request body): ") + UrlUtils.urlDecode(parameters)
HTTP_LOGGER.debug("Executing a POST to " + request.getUrl() + " with parameters "
+ (!binaryAttachments.isEmpty() ? "" : "(sent in request body): ")
+ UrlUtils.urlDecode(request.getParameters())
+ (!binaryAttachments.isEmpty() ? " and " + binaryAttachments.size() + " binary attachment[s]." : ""));
}

HttpURLConnection httpUrlConnection = null;
OutputStream outputStream = null;

try {
httpUrlConnection = openConnection(new URL(url + (!binaryAttachments.isEmpty() ? "?" + parameters : "")));
httpUrlConnection = openConnection(
new URL(request.getUrl() + (!binaryAttachments.isEmpty() ? "?" + request.getParameters() : "")));
httpUrlConnection.setReadTimeout(DEFAULT_READ_TIMEOUT_IN_MS);

// Allow subclasses to customize the connection if they'd like to - set
Expand All @@ -121,7 +112,7 @@ public Response executePost(String url, String parameters, List<BinaryAttachment
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setUseCaches(false);

initHeaderAccessToken(httpUrlConnection, headerAccessToken);
initHeaderAccessToken(httpUrlConnection, request);

if (!binaryAttachments.isEmpty()) {
httpUrlConnection.setRequestProperty("Connection", "Keep-Alive");
Expand Down Expand Up @@ -156,7 +147,7 @@ public Response executePost(String url, String parameters, List<BinaryAttachment
+ MULTIPART_TWO_HYPHENS + MULTIPART_CARRIAGE_RETURN_AND_NEWLINE).getBytes(StringUtils.ENCODING_CHARSET));
}
} else {
outputStream.write(parameters.getBytes(StringUtils.ENCODING_CHARSET));
outputStream.write(request.getParameters().getBytes(StringUtils.ENCODING_CHARSET));
}

HTTP_LOGGER.debug("Response headers: {}", httpUrlConnection.getHeaderFields());
Expand All @@ -177,9 +168,9 @@ public Response executePost(String url, String parameters, List<BinaryAttachment
}
}

protected void initHeaderAccessToken(HttpURLConnection httpUrlConnection, String headerAccessToken) {
if (headerAccessToken != null) {
httpUrlConnection.setRequestProperty("Authorization", "Bearer " + headerAccessToken);
protected void initHeaderAccessToken(HttpURLConnection httpUrlConnection, Request request) {
if (request.hasHeaderAccessToken()) {
httpUrlConnection.setRequestProperty("Authorization", "Bearer " + request.getHeaderAccessToken());
}
}

Expand All @@ -201,8 +192,8 @@ protected HttpURLConnection openConnection(URL url) throws IOException {

/**
* Hook method which allows subclasses to easily customize the {@code connection}s created by
* {@link #executeGet(String)} and {@link #executePost(String, String, String)} - for example, setting a custom read timeout
* or request header.
* {@link #executeGet(com.restfb.WebRequestor.Request)} and {@link #executePost(com.restfb.WebRequestor.Request)} -
* for example, setting a custom read timeout or request header.
* <p>
* This implementation is a no-op.
*
Expand Down Expand Up @@ -291,7 +282,8 @@ protected String createFormFieldName(BinaryAttachment binaryAttachment) {
}

String name = binaryAttachment.getFilename();
return Optional.ofNullable(name).filter(f -> f.contains(".")).map(f -> f.substring(0, f.lastIndexOf('.'))).orElse(name);
return Optional.ofNullable(name).filter(f -> f.contains(".")).map(f -> f.substring(0, f.lastIndexOf('.')))
.orElse(name);
}

/**
Expand Down Expand Up @@ -326,27 +318,28 @@ public Map<String, List<String>> getCurrentHeaders() {
}

@Override
public Response executeDelete(String url, String headerAccessToken) throws IOException {
return execute(url, HttpMethod.DELETE, headerAccessToken);
public Response executeDelete(Request request) throws IOException {
return execute(HttpMethod.DELETE, request);
}

@Override
public DebugHeaderInfo getDebugHeaderInfo() {
return debugHeaderInfo;
}

private Response execute(String url, HttpMethod httpMethod, String headerAccessToken) throws IOException {
HTTP_LOGGER.debug("Making a {} request to {}", httpMethod.name(), url);
private Response execute(HttpMethod httpMethod, Request request) throws IOException {
HTTP_LOGGER.debug("Making a {} request to {} with parameters {}", httpMethod.name(), request.getUrl(),
request.getParameters());

HttpURLConnection httpUrlConnection = null;

try {
httpUrlConnection = openConnection(new URL(url));
httpUrlConnection = openConnection(new URL(request.getFullUrl()));
httpUrlConnection.setReadTimeout(DEFAULT_READ_TIMEOUT_IN_MS);
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setRequestMethod(httpMethod.name());

initHeaderAccessToken(httpUrlConnection, headerAccessToken);
initHeaderAccessToken(httpUrlConnection, request);

// Allow subclasses to customize the connection if they'd like to - set
// their own headers, timeouts, etc.
Expand Down Expand Up @@ -374,7 +367,8 @@ protected void fillHeaderAndDebugInfo(HttpURLConnection httpUrlConnection) {
HTTP_LOGGER.debug("Facebook used the API {} to answer your request", usedApiVersion);

Version usedVersion = Version.getVersionFromString(usedApiVersion);
DebugHeaderInfo.DebugHeaderInfoFactory factory = DebugHeaderInfo.DebugHeaderInfoFactory.create().setVersion(usedVersion);
DebugHeaderInfo.DebugHeaderInfoFactory factory =
DebugHeaderInfo.DebugHeaderInfoFactory.create().setVersion(usedVersion);

Arrays.stream(FbHeaderField.values()).forEach(f -> f.getPutHeader().accept(httpUrlConnection, factory));
debugHeaderInfo = factory.build();
Expand All @@ -395,14 +389,13 @@ protected Response fetchResponse(HttpURLConnection httpUrlConnection) throws IOE
}

private enum FbHeaderField {
X_FB_TRACE_ID((c, f) -> f.setTraceId(getHeaderOrEmpty(c,"x-fb-trace-id"))), //
X_FB_REV((c, f) -> f.setRev(getHeaderOrEmpty(c,"x-fb-rev"))),
X_FB_DEBUG((c, f) -> f.setDebug(getHeaderOrEmpty(c,"x-fb-debug"))),
X_APP_USAGE((c, f) -> f.setAppUsage(getHeaderOrEmpty(c,"x-app-usage"))),
X_PAGE_USAGE((c, f) -> f.setPageUsage(getHeaderOrEmpty(c,"x-page-usage"))),
X_AD_ACCOUNT_USAGE((c, f) -> f.setAdAccountUsage(getHeaderOrEmpty(c,"x-ad-account-usage"))),
X_BUSINESS_USE_CASE_USAGE((c, f) -> f.setBusinessUseCaseUsage(getHeaderOrEmpty(c,"x-business-use-case-usage")));

X_FB_TRACE_ID((c, f) -> f.setTraceId(getHeaderOrEmpty(c, "x-fb-trace-id"))), //
X_FB_REV((c, f) -> f.setRev(getHeaderOrEmpty(c, "x-fb-rev"))), //
X_FB_DEBUG((c, f) -> f.setDebug(getHeaderOrEmpty(c, "x-fb-debug"))), //
X_APP_USAGE((c, f) -> f.setAppUsage(getHeaderOrEmpty(c, "x-app-usage"))), //
X_PAGE_USAGE((c, f) -> f.setPageUsage(getHeaderOrEmpty(c, "x-page-usage"))), //
X_AD_ACCOUNT_USAGE((c, f) -> f.setAdAccountUsage(getHeaderOrEmpty(c, "x-ad-account-usage"))), //
X_BUSINESS_USE_CASE_USAGE((c, f) -> f.setBusinessUseCaseUsage(getHeaderOrEmpty(c, "x-business-use-case-usage")));

private final BiConsumer<HttpURLConnection, DebugHeaderInfo.DebugHeaderInfoFactory> putHeader;

Expand Down

0 comments on commit 1523c82

Please sign in to comment.