From 1ec6286158cf63149b6095c23127106ef7789b6b Mon Sep 17 00:00:00 2001 From: deagrawa Date: Tue, 26 Feb 2019 12:18:37 +0530 Subject: [PATCH 01/10] Changes to move dependency from Apache HttpClient to OkHttp in httpcore module --- build.gradle | 7 +- .../graph/httpcore/AuthenticationHandler.java | 17 +-- .../microsoft/graph/httpcore/HttpClients.java | 31 ++-- .../httpcore/IAuthenticationProvider.java | 4 +- .../graph/httpcore/RedirectHandler.java | 134 +++++++++++------- .../graph/httpcore/RetryHandler.java | 77 +++++----- .../middlewareoption/IShouldRetry.java | 6 +- .../middlewareoption/RetryOptions.java | 6 +- 8 files changed, 149 insertions(+), 133 deletions(-) diff --git a/build.gradle b/build.gradle index c81d1d2ce..261f884bc 100644 --- a/build.gradle +++ b/build.gradle @@ -23,11 +23,6 @@ repositories { mavenCentral() } -def platformDependency = "org.apache.httpcomponents:httpclient:4.5.6" -if ( project.hasProperty("platform") && project.platform == "android" ) { - platformDependency = "org.apache.httpcomponents:httpclient-android:4.3.5" -} - dependencies { // This dependency is exported to consumers, that is to say found on their compile classpath. api 'org.apache.commons:commons-math3:3.6.1' @@ -38,7 +33,7 @@ dependencies { // Use JUnit test framework testImplementation 'junit:junit:4.12' - api platformDependency + api 'com.squareup.okhttp3:okhttp:3.12.1' // https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1' diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index 1657df1d3..b7eb1003c 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -2,22 +2,23 @@ import java.io.IOException; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.protocol.HttpContext; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; -public class AuthenticationHandler implements HttpRequestInterceptor { +public class AuthenticationHandler implements Interceptor { private IAuthenticationProvider authProvider; public AuthenticationHandler(IAuthenticationProvider authProvider) { this.authProvider = authProvider; } - + @Override - public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - authProvider.authenticateRequest(request); + public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + Request authenticatedRequest = authProvider.authenticateRequest(originalRequest); + return chain.proceed(authenticatedRequest); } } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index e51eb5921..65e53490b 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -1,8 +1,7 @@ package com.microsoft.graph.httpcore; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import okhttp3.OkHttpClient; +import okhttp3.OkHttpClient.Builder; public class HttpClients { private HttpClients() { @@ -11,31 +10,21 @@ private HttpClients() { /** * Creates builder object for construction of custom - * {@link CloseableHttpClient} instances. + * {@link OkHttpClient} instances. */ - public static HttpClientBuilder custom() { - return HttpClientBuilder.create(); + public static Builder custom() { + return new OkHttpClient.Builder(); } /** - * Creates {@link CloseableHttpClient} instance with default + * Creates {@link OkHttpClient} instance with default * configuration and provided authProvider */ - public static CloseableHttpClient createDefault(IAuthenticationProvider auth) { - RequestConfig config = RequestConfig.custom().setMaxRedirects(5).build(); + public static OkHttpClient createDefault(IAuthenticationProvider auth) { - return HttpClientBuilder.create().addInterceptorFirst(new AuthenticationHandler(auth)) - .setRedirectStrategy(new RedirectHandler()) - .setServiceUnavailableRetryStrategy(new RetryHandler()) - .setDefaultRequestConfig(config) + return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) + .addInterceptor(new RetryHandler()) + .addInterceptor(new RedirectHandler()) .build(); } - - /** - * Creates {@link CloseableHttpClient} instance with default - * configuration based on system properties. - */ - public static CloseableHttpClient createSystem() { - return HttpClientBuilder.create().useSystemProperties().build(); - } } diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index f3312f588..10c64a6f7 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -1,6 +1,6 @@ package com.microsoft.graph.httpcore; -import org.apache.http.HttpRequest; +import okhttp3.Request; public interface IAuthenticationProvider { /** @@ -8,5 +8,5 @@ public interface IAuthenticationProvider { * * @param request the request to authenticate */ - void authenticateRequest(HttpRequest request); + Request authenticateRequest(Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 1fe483272..cb1882829 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -1,67 +1,101 @@ package com.microsoft.graph.httpcore; -import java.net.URI; -import java.net.URISyntaxException; +import static java.net.HttpURLConnection.HTTP_MOVED_PERM; +import static java.net.HttpURLConnection.HTTP_MOVED_TEMP; +import static java.net.HttpURLConnection.HTTP_SEE_OTHER; +import static okhttp3.internal.http.StatusLine.HTTP_PERM_REDIRECT; +import static okhttp3.internal.http.StatusLine.HTTP_TEMP_REDIRECT; -import org.apache.http.Header; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.ProtocolException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.protocol.HttpContext; -import org.apache.http.util.Args; +import java.io.IOException; +import java.net.ProtocolException; -public class RedirectHandler extends DefaultRedirectStrategy{ +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.internal.http.HttpMethod; + +public class RedirectHandler implements Interceptor{ public static final RedirectHandler INSTANCE = new RedirectHandler(); + final int maxRedirect = 5; - @Override - public boolean isRedirected( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws ProtocolException { - Args.notNull(request, "HTTP request"); - Args.notNull(response, "HTTP response"); - - final int statusCode = response.getStatusLine().getStatusCode(); - final Header locationHeader = response.getFirstHeader("location"); + public boolean isRedirected(Request request, Response response, int redirectCount) throws IOException { + + if(redirectCount > maxRedirect) return false; + + final String locationHeader = response.header("location"); if(locationHeader == null) return false; - if(statusCode == HttpStatus.SC_MOVED_TEMPORARILY || - statusCode == HttpStatus.SC_MOVED_PERMANENTLY || - statusCode == HttpStatus.SC_TEMPORARY_REDIRECT || - statusCode == HttpStatus.SC_SEE_OTHER || - statusCode == 308) + final int statusCode = response.code(); + if(statusCode == HTTP_PERM_REDIRECT || + statusCode == HTTP_MOVED_PERM || + statusCode == HTTP_TEMP_REDIRECT || + statusCode == HTTP_SEE_OTHER || + statusCode == HTTP_MOVED_TEMP) return true; return false; } - @Override - public HttpUriRequest getRedirect( - final HttpRequest request, - final HttpResponse response, - final HttpContext context) throws ProtocolException { - final URI uri = getLocationURI(request, response, context); - try { - final URI requestURI = new URI(request.getRequestLine().getUri()); - if(!uri.getHost().equalsIgnoreCase(requestURI.getHost()) || - !uri.getScheme().equalsIgnoreCase(requestURI.getScheme())) - request.removeHeaders("Authorization"); - } - catch (final URISyntaxException ex) { - throw new ProtocolException(ex.getMessage(), ex); - } - - final int status = response.getStatusLine().getStatusCode(); - if(status == HttpStatus.SC_SEE_OTHER) - return new HttpGet(uri); - return RequestBuilder.copy(request).setUri(uri).build(); + public Request getRedirect( + final Request request, + final Response userResponse) throws ProtocolException { + String location = userResponse.header("Location"); + if (location == null) return null; + HttpUrl url = userResponse.request().url().resolve(location); + // Don't follow redirects to unsupported protocols. + if (url == null) return null; + + // Most redirects don't include a request body. + Request.Builder requestBuilder = userResponse.request().newBuilder(); + final String method = userResponse.request().method(); + + if (HttpMethod.permitsRequestBody(method)) { + final boolean maintainBody = HttpMethod.redirectsWithBody(method); + if (HttpMethod.redirectsToGet(method)) { + requestBuilder.method("GET", null); + } else { + RequestBody requestBody = maintainBody ? userResponse.request().body() : null; + requestBuilder.method(method, requestBody); + } + if (!maintainBody) { + requestBuilder.removeHeader("Transfer-Encoding"); + requestBuilder.removeHeader("Content-Length"); + requestBuilder.removeHeader("Content-Type"); + } + } + + // When redirecting across hosts, drop all authentication headers. This + // is potentially annoying to the application layer since they have no + // way to retain them. + boolean sameScheme = url.scheme().equals(userResponse.request().url().scheme()); + boolean sameHost = url.host().equals(userResponse.request().url().host()); + if (!sameScheme || !sameHost) { + requestBuilder.removeHeader("Authorization"); + } + + return requestBuilder.url(url).build(); } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = null; + int redirectCount = 1; + while(true) { + response = chain.proceed(request); + boolean shouldRedirect = isRedirected(request, response, redirectCount); + if(!shouldRedirect) break; + + Request followup = getRedirect(request, response); + if(followup == null) break; + request = followup; + + redirectCount++; + } + return response; + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 77de83f11..237dfed87 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -1,22 +1,14 @@ package com.microsoft.graph.httpcore; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.client.ServiceUnavailableRetryStrategy; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.client.methods.HttpPatch; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.protocol.HttpContext; -import org.apache.http.protocol.HttpCoreContext; -import org.apache.http.util.Args; +import java.io.IOException; -import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; -public class RetryHandler implements ServiceUnavailableRetryStrategy{ +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class RetryHandler implements Interceptor{ /** * Maximum number of allowed retries if the server responds with a HTTP code @@ -47,32 +39,30 @@ public RetryHandler() { this(null); } - @Override - public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { + public boolean retryRequest(Response response, int executionCount, Request request) { - RetryOptions retryOption = (RetryOptions)context.getAttribute(MiddlewareType.RETRY.toString()); + RetryOptions retryOption = request.tag(RetryOptions.class); if(retryOption != null) { - return retryOption.shouldRetry().shouldRetry(response, executionCount, context); + return retryOption.shouldRetry().shouldRetry(response, executionCount, request); } if(mRetryOption != null) { - return mRetryOption.shouldRetry().shouldRetry(response, executionCount, context); + return mRetryOption.shouldRetry().shouldRetry(response, executionCount, request); } boolean shouldRetry = false; - int statusCode = response.getStatusLine().getStatusCode(); - shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, context); + int statusCode = response.code(); + shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, request); if(shouldRetry) { - Header header = response.getFirstHeader(RETRY_AFTER); - if(header != null) - retryInterval = Long.parseLong(header.getValue()); + String retryAfterHeader = response.header(RETRY_AFTER); + if(retryAfterHeader != null) + retryInterval = Long.parseLong(retryAfterHeader); else retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; } return shouldRetry; } - @Override public long getRetryInterval() { return retryInterval; } @@ -84,27 +74,34 @@ private boolean checkStatus(int statusCode) { return false; } - private boolean isBuffered(HttpResponse response, HttpContext context) { - HttpRequest request = (HttpRequest)context.getAttribute( HttpCoreContext.HTTP_REQUEST); - String methodName = request.getRequestLine().getMethod(); + private boolean isBuffered(Response response, Request request) { + String methodName = request.method(); - boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase(HttpPost.METHOD_NAME) || - methodName.equalsIgnoreCase(HttpPut.METHOD_NAME) || - methodName.equalsIgnoreCase(HttpPatch.METHOD_NAME); + boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || + methodName.equalsIgnoreCase("PUT") || + methodName.equalsIgnoreCase("PATCH"); - Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); + //Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); + String transferEncoding = response.header(TRANSFER_ENCODING); boolean isTransferEncodingChunked = (transferEncoding != null) && - transferEncoding.getValue().equalsIgnoreCase("chunked"); - - HttpEntity entity = null; - if(request instanceof HttpEntityEnclosingRequestBase) { - HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; - entity = httprequest.getEntity(); - } + transferEncoding.equalsIgnoreCase("chunked"); - if(entity != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) + if(request.body() != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) return false; return true; } + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + Response response = chain.proceed(request); + int executionCount = 0; + while(retryRequest(response, executionCount, request)) { + executionCount++; + response = chain.proceed(request); + } + return response; + } + } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index cd208e0ca..366c310a6 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -1,8 +1,8 @@ package com.microsoft.graph.httpcore.middlewareoption; -import org.apache.http.HttpResponse; -import org.apache.http.protocol.HttpContext; +import okhttp3.Request; +import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context); + boolean shouldRetry(Response response, int executionCount, Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index 867108389..57ccfbc29 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -1,14 +1,14 @@ package com.microsoft.graph.httpcore.middlewareoption; -import org.apache.http.HttpResponse; -import org.apache.http.protocol.HttpContext; +import okhttp3.Request; +import okhttp3.Response; public class RetryOptions implements IMiddlewareControl { private IShouldRetry shouldretry; public RetryOptions(){ this(new IShouldRetry() { - public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + public boolean shouldRetry(Response response, int executionCount, Request request) { return true; } }); From d644fda2ab59662769a0cd147922454ede2eed96 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Mon, 4 Mar 2019 18:38:45 +0530 Subject: [PATCH 02/10] Added okhttp to batch request, redirect --- .../graph/content/MSBatchRequestContent.java | 159 ++++++++++-------- .../graph/content/MSBatchRequestStep.java | 17 +- .../graph/content/MSBatchResponseContent.java | 33 ++-- .../microsoft/graph/httpcore/HttpClients.java | 1 - .../graph/httpcore/RedirectHandler.java | 39 ++--- .../content/MSBatchRequestContentTest.java | 27 ++- .../graph/content/MSBatchRequestStepTest.java | 8 +- .../content/MSBatchResponseContentTest.java | 14 +- .../httpcore/AuthenticationHandlerTest.java | 12 +- .../graph/httpcore/HttpClientsTest.java | 15 +- .../graph/httpcore/RedirectHandlerTest.java | 60 ++++--- .../graph/httpcore/RetryHandlerTest.java | 28 +-- 12 files changed, 215 insertions(+), 198 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 17040beea..b944f9e32 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -1,112 +1,127 @@ package com.microsoft.graph.content; -import java.util.ArrayList; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.util.EntityUtils; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.json.simple.JSONValue; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import okhttp3.Headers; +import okhttp3.Request; +import okhttp3.RequestBody; +import okio.Buffer; public class MSBatchRequestContent { - private List batchRequestStepsArray; + private Map batchRequestStepsHashMap; private final int maxNumberOfRequests = 20; public MSBatchRequestContent(List batchRequestStepsArray) { - this.batchRequestStepsArray = new ArrayList<>(); - if(batchRequestStepsArray.size() <= maxNumberOfRequests) { - for(MSBatchRequestStep requestStep: batchRequestStepsArray) - addBatchRequestStep(requestStep); - } + if(batchRequestStepsArray.size() > maxNumberOfRequests) + throw new IllegalArgumentException("Number of batch request steps cannot exceed 20."); + + this.batchRequestStepsHashMap = new HashMap<>(); + for(MSBatchRequestStep requestStep: batchRequestStepsArray) + addBatchRequestStep(requestStep); } public MSBatchRequestContent() { - batchRequestStepsArray = new ArrayList<>(); + batchRequestStepsHashMap = new HashMap(); } public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { - if(batchRequestStep.getRequestId().compareTo("") == 0) - return false; - if(batchRequestStepsArray.size() == maxNumberOfRequests) + if(batchRequestStepsHashMap.containsKey(batchRequestStep.getRequestId())) return false; - for(MSBatchRequestStep requestStep: batchRequestStepsArray) { - if(batchRequestStep.getRequestId().compareTo(requestStep.getRequestId()) == 0) - return false; - } - return batchRequestStepsArray.add(batchRequestStep); + batchRequestStepsHashMap.put(batchRequestStep.getRequestId(), batchRequestStep); + return true; } - public boolean removeBatchRequesStepWithId(String requestId) { - boolean ret = false; - for (int i = batchRequestStepsArray.size()-1; i >= 0; i--) - { - MSBatchRequestStep requestStep = batchRequestStepsArray.get(i); - for (int j = requestStep.getArrayOfDependsOnIds().size() - 1; j >= 0; j--) - { - String dependsOnId = requestStep.getArrayOfDependsOnIds().get(j); - if(dependsOnId.compareTo(requestId) == 0) - { - requestStep.getArrayOfDependsOnIds().remove(j); - ret = true; - } - } - if(requestId.compareTo(requestStep.getRequestId()) == 0) { - batchRequestStepsArray.remove(i); - ret = true; - } - } - return ret; + public boolean removeBatchRequestStepWithId(String requestId) { + boolean removed = false; + if(batchRequestStepsHashMap.containsKey(requestId)) { + batchRequestStepsHashMap.remove(requestId); + removed = true; + } + for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)) + removed = true; + } + return removed; } + @SuppressWarnings("unchecked") public String getBatchRequestContent() { - Map>> batchRequestContentMap = new HashMap<>(); - List> batchContentArray = new ArrayList<>(); - for(MSBatchRequestStep requestStep : batchRequestStepsArray) { - batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep)); + JSONObject batchRequestContentMap = new JSONObject(); + JSONArray batchContentArray = new JSONArray(); + for(Map.Entry requestStep : batchRequestStepsHashMap.entrySet()) { + batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep.getValue())); } batchRequestContentMap.put("requests", batchContentArray); - return JSONValue.toJSONString(batchRequestContentMap); + return batchRequestContentMap.toJSONString(); } - private Map getBatchRequestMapFromRequestStep(MSBatchRequestStep batchRequestStep){ - Map contentmap = new HashMap<>(); + @SuppressWarnings("unchecked") + private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep batchRequestStep){ + JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); - contentmap.put("url", batchRequestStep.getRequest().getRequestLine().getUri()); - contentmap.put("method", batchRequestStep.getRequest().getRequestLine().getMethod()); - Header[] headers = batchRequestStep.getRequest().getAllHeaders(); - if(headers != null && headers.length != 0) { - JSONObject obj = new JSONObject(); - for(Header header: headers) { - obj.put(header.getName(), header.getValue()); + + String url = batchRequestStep.getRequest().url().toString(); + url = url.replaceAll("https://graph.microsoft.com/v1.0", ""); + url = url.replace("https://graph.microsoft.com/beta", ""); + contentmap.put("url", url); + + contentmap.put("method", batchRequestStep.getRequest().method().toString()); + + Headers headers = batchRequestStep.getRequest().headers(); + if(headers != null && headers.size() != 0) { + JSONObject headerMap = new JSONObject(); + for(Map.Entry> entry : headers.toMultimap().entrySet()) { + headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); } - contentmap.put("headers", obj.toJSONString()); + contentmap.put("headers", headerMap); } - HttpEntity entity = null; - HttpRequest request = batchRequestStep.getRequest(); - if(request instanceof HttpEntityEnclosingRequestBase) { - HttpEntityEnclosingRequestBase httprequest = (HttpEntityEnclosingRequestBase)request; - entity = httprequest.getEntity(); + + List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); + if(arrayOfDependsOnIds != null) { + JSONArray array = new JSONArray(); + for(String dependsOnId : arrayOfDependsOnIds) array.add(dependsOnId); + contentmap.put("dependsOn", array); } - if(entity != null) { + + RequestBody body = batchRequestStep.getRequest().body(); + if(body != null) { try { - String body = EntityUtils.toString(entity); - contentmap.put("body", body); - } - catch(Exception e) { + contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); + }catch(IOException | ParseException e) { e.printStackTrace(); - } - } - List arrayOfDependsOnIds = batchRequestStep.getArrayOfDependsOnIds(); - if(arrayOfDependsOnIds != null) { - contentmap.put("dependsOn", JSONValue.toJSONString(arrayOfDependsOnIds)); + } } return contentmap; } + + private String getHeaderValuesAsString(final List list) { + StringBuilder builder = new StringBuilder(""); + if(list.size() != 0) { + builder.append(list.get(0)); + for(int i=1;i arrayOfDependsOnIds; - public MSBatchRequestStep(String requestId, HttpRequest request, List arrayOfDependsOnIds) { + public MSBatchRequestStep(String requestId, Request request, List arrayOfDependsOnIds) { + if(requestId == null) + throw new IllegalArgumentException("Request Id cannot be null."); + if(request == null) + new IllegalArgumentException("Request cannot be null."); + if(request.url() == null) + throw new IllegalArgumentException("Request url cannot be null."); + if(request.method() == null) + throw new IllegalArgumentException("Request method cannot be null."); + this.requestId = requestId; this.request = request; this.arrayOfDependsOnIds = arrayOfDependsOnIds; @@ -19,7 +28,7 @@ public String getRequestId() { return requestId; } - public HttpRequest getRequest() { + public Request getRequest() { return request; } diff --git a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java index 42c0f44dc..b08f494a8 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchResponseContent.java @@ -1,20 +1,19 @@ package com.microsoft.graph.content; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHttpResponse; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import okhttp3.MediaType; +import okhttp3.Response; +import okhttp3.ResponseBody; + public class MSBatchResponseContent { private JSONObject batchResponseObj; - public MSBatchResponseContent(String batchResponseData ) { + public MSBatchResponseContent(String batchResponseData) { JSONParser parser = new JSONParser(); try { if(batchResponseData != null) @@ -25,7 +24,7 @@ public MSBatchResponseContent(String batchResponseData ) { } } - public HttpResponse getResponseById(String requestId) { + public Response getResponseById(String requestId) { if(batchResponseObj == null) return null; @@ -37,21 +36,29 @@ public HttpResponse getResponseById(String requestId) { JSONObject jsonresponse = (JSONObject)response; String id = (String)jsonresponse.get("id"); if(id.compareTo(requestId) == 0) { - HttpResponse httpresponse = new BasicHttpResponse(null, ((Long)jsonresponse.get("status")).intValue(), null); + Response.Builder builder = new Response.Builder(); + + if(jsonresponse.get("status") != null) { + String status = (String)jsonresponse.get("status"); + builder.code(Integer.parseInt(status)); + } + if(jsonresponse.get("body") != null) { - HttpEntity entity = new StringEntity(jsonresponse.get("body").toString(), ContentType.APPLICATION_JSON); - httpresponse.setEntity(entity); + String bodyAsString = (String)jsonresponse.get("body"); + ResponseBody responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.body(responseBody); } if(jsonresponse.get("headers") != null){ JSONObject jsonheaders = (JSONObject)jsonresponse.get("headers"); for(Object key: jsonheaders.keySet()) { String strkey = (String)key; String strvalue = (String)jsonheaders.get(strkey); - httpresponse.setHeader(strkey, strvalue); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } } } - return httpresponse; - + return builder.build(); } } return null; diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 65e53490b..dc5ddbdba 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -21,7 +21,6 @@ public static Builder custom() { * configuration and provided authProvider */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { - return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index cb1882829..093d90115 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -30,11 +30,11 @@ public boolean isRedirected(Request request, Response response, int redirectCoun return false; final int statusCode = response.code(); - if(statusCode == HTTP_PERM_REDIRECT || - statusCode == HTTP_MOVED_PERM || - statusCode == HTTP_TEMP_REDIRECT || - statusCode == HTTP_SEE_OTHER || - statusCode == HTTP_MOVED_TEMP) + if(statusCode == HTTP_PERM_REDIRECT || //308 + statusCode == HTTP_MOVED_PERM || //301 + statusCode == HTTP_TEMP_REDIRECT || //307 + statusCode == HTTP_SEE_OTHER || //303 + statusCode == HTTP_MOVED_TEMP) //302 return true; return false; @@ -45,39 +45,26 @@ public Request getRedirect( final Response userResponse) throws ProtocolException { String location = userResponse.header("Location"); if (location == null) return null; - HttpUrl url = userResponse.request().url().resolve(location); + + HttpUrl requestUrl = userResponse.request().url(); + + HttpUrl locationUrl = userResponse.request().url().resolve(location); // Don't follow redirects to unsupported protocols. - if (url == null) return null; + if (locationUrl == null) return null; // Most redirects don't include a request body. Request.Builder requestBuilder = userResponse.request().newBuilder(); - final String method = userResponse.request().method(); - - if (HttpMethod.permitsRequestBody(method)) { - final boolean maintainBody = HttpMethod.redirectsWithBody(method); - if (HttpMethod.redirectsToGet(method)) { - requestBuilder.method("GET", null); - } else { - RequestBody requestBody = maintainBody ? userResponse.request().body() : null; - requestBuilder.method(method, requestBody); - } - if (!maintainBody) { - requestBuilder.removeHeader("Transfer-Encoding"); - requestBuilder.removeHeader("Content-Length"); - requestBuilder.removeHeader("Content-Type"); - } - } // When redirecting across hosts, drop all authentication headers. This // is potentially annoying to the application layer since they have no // way to retain them. - boolean sameScheme = url.scheme().equals(userResponse.request().url().scheme()); - boolean sameHost = url.host().equals(userResponse.request().url().host()); + boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); + boolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); if (!sameScheme || !sameHost) { requestBuilder.removeHeader("Authorization"); } - return requestBuilder.url(url).build(); + return requestBuilder.url(locationUrl).build(); } @Override diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index c15448051..a4c37813a 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -1,18 +1,14 @@ package com.microsoft.graph.content; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpGet; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; +import okhttp3.Request; + public class MSBatchRequestContentTest { String testurl = "http://graph.microsoft.com"; @@ -21,7 +17,7 @@ public class MSBatchRequestContentTest { public void testMSBatchRequestContentCreation() { List requestStepArray = new ArrayList<>(); for(int i=0;i<5;i++) { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); requestStepArray.add(requestStep); @@ -32,7 +28,7 @@ public void testMSBatchRequestContentCreation() { @Test public void testGetBatchRequestContent() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); @@ -44,8 +40,7 @@ public void testGetBatchRequestContent() { @Test public void testGetBatchRequestContentWithHeader() { - HttpRequest request = new HttpGet(testurl); - request.setHeader("testkey", "testvalue"); + Request request = new Request.Builder().url(testurl).header("testkey", "testvalue").build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); @@ -57,12 +52,12 @@ public void testGetBatchRequestContentWithHeader() { @Test public void testRemoveBatchRequesStepWithId() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); MSBatchRequestContent requestContent = new MSBatchRequestContent(); requestContent.addBatchRequestStep(requestStep); - requestContent.removeBatchRequesStepWithId("1"); + requestContent.removeBatchRequestStepWithId("1"); String content = requestContent.getBatchRequestContent(); String expectedContent = "{\"requests\":[]}"; assertTrue(content.compareTo(expectedContent) == 0); @@ -70,11 +65,11 @@ public void testRemoveBatchRequesStepWithId() { @Test public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { - HttpRequest request = new HttpGet(testurl); + Request request = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - HttpRequest request1 = new HttpGet(testurl); + Request request1 = new Request.Builder().url(testurl).build(); List arrayOfDependsOnIds1 = new ArrayList<>(); arrayOfDependsOnIds1.add("1"); MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); @@ -83,7 +78,7 @@ public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { requestContent.addBatchRequestStep(requestStep); requestContent.addBatchRequestStep(requestStep1); - requestContent.removeBatchRequesStepWithId("1"); + requestContent.removeBatchRequestStepWithId("1"); String content = requestContent.getBatchRequestContent(); String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; assertTrue(content.compareTo(expectedContent) == 0); diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java index fa98ec302..d17af87a2 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestStepTest.java @@ -5,16 +5,16 @@ import java.util.ArrayList; import java.util.List; -import org.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpGet; import org.junit.Test; +import okhttp3.Request; + public class MSBatchRequestStepTest { @Test public void testMSBatchRequestStepCreation() { - HttpRequest request = new HttpGet("http://graph.microsoft.com"); - List arrayOfDependsOnIds = new ArrayList(); + Request request = new Request.Builder().url("http://graph.microsoft.com").build(); + List arrayOfDependsOnIds = new ArrayList<>(); MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); assertTrue("Test BatchRequestStep creation", requestStep != null); assertTrue("Test Request id", requestStep.getRequestId().compareTo("1") == 0); diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index bf9652aff..1eebc8219 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -2,18 +2,10 @@ import static org.junit.Assert.assertTrue; -import java.io.IOException; -import java.util.Arrays; - -import org.apache.http.HttpResponse; -import org.apache.http.ParseException; -import org.apache.http.util.EntityUtils; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; +import okhttp3.Response; + public class MSBatchResponseContentTest { @Test @@ -54,7 +46,7 @@ public void testInvalidMSBatchResponseContentWithMalformedResponse() { public void testGetMSBatchResponseContentByID() { String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); - HttpResponse response = batchresponse.getResponseById("1"); + Response response = batchresponse.getResponseById("1"); assertTrue(response != null); } } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index dbd855760..a0bfccbb6 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -5,20 +5,22 @@ import java.io.IOException; -import org.apache.http.Header; import org.apache.http.HttpException; -import org.apache.http.HttpRequest; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; import org.junit.Test; +import okhttp3.Request; +import okhttp3.internal.http2.Header; + public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; public static class AuthProvider implements IAuthenticationProvider{ - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", "Bearer " + token); + public Request authenticateRequest(Request request) { + Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + token).build(); + return newRequest; } } @@ -26,7 +28,7 @@ public void authenticateRequest(HttpRequest request) { public void testAuthenticationHandler() { AuthProvider authProvider = new AuthProvider(); AuthenticationHandler authHandler = new AuthenticationHandler(authProvider); - HttpGet httpget = new HttpGet("https://graph.microsoft.com/v1.0/me/"); + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/").build(); HttpClientContext localContext = HttpClientContext.create(); try { diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index c084f69fc..feee259b1 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -2,20 +2,23 @@ import static org.junit.Assert.assertTrue; -import org.apache.http.HttpRequest; -import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Test; +import okhttp3.OkHttpClient; +import okhttp3.Request; + public class HttpClientsTest { @Test public void testHttpClientCreation() { IAuthenticationProvider authprovider = new IAuthenticationProvider() { - public void authenticateRequest(HttpRequest request) { - request.addHeader("Authorization", "Bearer " + "TOKEN"); - } + public Request authenticateRequest(Request request) { + Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + "TOKEN").build(); + return newRequest; + } }; - CloseableHttpClient httpclient = HttpClients.createDefault(authprovider); + + OkHttpClient httpclient = HttpClients.createDefault(authprovider); assertTrue(httpclient != null); } diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index 1e998f761..f53fe097b 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -3,12 +3,12 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import org.apache.http.Header; +import java.net.ProtocolException; + import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; -import org.apache.http.ProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; @@ -16,6 +16,10 @@ import org.apache.http.message.BasicHttpResponse; import org.junit.Test; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.internal.http2.Header; + public class RedirectHandlerTest { String testmeurl = "https://graph.microsoft.com/v1.0/me/"; @@ -25,8 +29,8 @@ public class RedirectHandlerTest { @Test public void testIsRedirectedFailureByNoLocationHeader() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); HttpClientContext localContext = HttpClientContext.create(); try { boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); @@ -40,8 +44,8 @@ public void testIsRedirectedFailureByNoLocationHeader() { @Test public void testIsRedirectedFailureByStatusCodeBadRequest() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -56,8 +60,8 @@ public void testIsRedirectedFailureByStatusCodeBadRequest() { @Test public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -72,8 +76,8 @@ public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { @Test public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -88,8 +92,8 @@ public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { @Test public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); + Request httpget = new HttpGet(testmeurl); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -104,8 +108,8 @@ public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { @Test public void testIsRedirectedSuccessWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testmeurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { @@ -120,12 +124,12 @@ public void testIsRedirectedSuccessWithStatusCodeSeeOther() { @Test public void testGetRedirectForGetMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httpget = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); @@ -138,13 +142,13 @@ public void testGetRedirectForGetMethod() { @Test public void testGetRedirectForGetMethodForAuthHeader() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpGet httpget = new HttpGet(testurl); + Request httpget = new Request.Builder().url(testurl).build(); httpget.addHeader("Authorization", "TOKEN"); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", differenthosturl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); @@ -160,11 +164,11 @@ public void testGetRedirectForGetMethodForAuthHeader() { public void testGetRedirectForHeadMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; HttpHead httphead = new HttpHead(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httphead, response, localContext); + Request request = redirectHandler.getRedirect(httphead, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); @@ -177,12 +181,12 @@ public void testGetRedirectForHeadMethod() { @Test public void testGetRedirectForPostMethod() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); + Request httppost = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); @@ -195,12 +199,12 @@ public void testGetRedirectForPostMethod() { @Test public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpPost httppost = new HttpPost(testurl); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); + Request httppost = new Request.Builder().url(testurl).build(); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); response.setHeader("location", testmeurl); HttpClientContext localContext = HttpClientContext.create(); try { - HttpRequest request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response, localContext); assertTrue(request != null); final String method = request.getRequestLine().getMethod(); assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 36082894e..06299fe1f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -6,6 +6,8 @@ import java.io.UnsupportedEncodingException; +import javax.xml.ws.spi.http.HttpContext; + import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -14,13 +16,15 @@ import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpCoreContext; import org.junit.Test; import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import okhttp3.Request; +import okhttp3.Response; + public class RetryHandlerTest { int maxRetries = 2; @@ -37,7 +41,7 @@ public void testRetryHandlerCreation() { public void testRetryHandlerWithRetryOptions() { RetryOptions option = new RetryOptions(); RetryHandler retryhandler = new RetryHandler(option); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertTrue(retryhandler.retryRequest(response, 1, localContext)); } @@ -45,12 +49,12 @@ public void testRetryHandlerWithRetryOptions() { @Test public void testRetryHandlerWithCustomRetryOptions() { RetryOptions option = new RetryOptions(new IShouldRetry() { - public boolean shouldRetry(HttpResponse response, int executionCount, HttpContext context) { + public boolean shouldRetry(Response response, int executionCount, HttpContext context) { return false; } }); RetryHandler retryhandler = new RetryHandler(option); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertTrue(!retryhandler.retryRequest(response, 1, localContext)); } @@ -58,7 +62,7 @@ public boolean shouldRetry(HttpResponse response, int executionCount, HttpContex @Test public void testRetryRequestWithMaxRetryAttempts() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 3, localContext)); } @@ -66,7 +70,7 @@ public void testRetryRequestWithMaxRetryAttempts() { @Test public void testRetryRequestForStatusCode() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); HttpClientContext localContext = HttpClientContext.create(); assertFalse(retryhandler.retryRequest(response, 1, localContext)); } @@ -74,9 +78,9 @@ public void testRetryRequestForStatusCode() { @Test public void testRetryRequestWithTransferEncoding() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Transfer-Encoding", "chunked"); - HttpPost httppost = new HttpPost(testurl); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); @@ -94,8 +98,8 @@ public void testRetryRequestWithTransferEncoding() { @Test public void testRetryRequestWithExponentialBackOff() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - HttpPost httppost = new HttpPost(testurl); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); @@ -114,9 +118,9 @@ public void testRetryRequestWithExponentialBackOff() { @Test public void testRetryHandlerRetryRequestWithRetryAfterHeader() { RetryHandler retryhandler = new RetryHandler(); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); + Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); response.setHeader("Retry-After", "100"); - HttpPost httppost = new HttpPost(testurl); + Request httppost = new Request.Builder().url(testurl).build(); try { HttpEntity entity = new StringEntity("TEST"); From 76a447d3c8aacb0d78981851e4b97db35f717d80 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:04:18 +0530 Subject: [PATCH 03/10] Added redirect options --- .../middlewareoption/IShouldRedirect.java | 7 +++ .../middlewareoption/RedirectOptions.java | 52 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java create mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java new file mode 100644 index 000000000..8ca9cd545 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRedirect.java @@ -0,0 +1,7 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import okhttp3.Response; + +public interface IShouldRedirect { + boolean shouldRedirect(final Response response); +} diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java new file mode 100644 index 000000000..f4ef54900 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RedirectOptions.java @@ -0,0 +1,52 @@ +package com.microsoft.graph.httpcore.middlewareoption; + +import okhttp3.Response; + +public class RedirectOptions implements IMiddlewareControl{ + private int maxRedirects; + public static final int DEFAULT_MAX_REDIRECTS = 5; + public static final int MAX_REDIRECTS = 20; + + private IShouldRedirect shouldRedirect; + public static final IShouldRedirect DEFAULT_SHOULD_REDIRECT = new IShouldRedirect() { + @Override + public boolean shouldRedirect(Response response) { + return true; + } + }; + + /* + * Create default instance of redirect options, with default values of max redirects and should redirect + */ + public RedirectOptions() { + this(DEFAULT_MAX_REDIRECTS, DEFAULT_SHOULD_REDIRECT); + } + + /* + * @param maxRedirects Max redirects to occur + * @param shouldRedirect Should redirect callback called before every redirect + */ + public RedirectOptions(int maxRedirects, IShouldRedirect shouldRedirect) { + if(maxRedirects < 0) + throw new IllegalArgumentException("Max redirects cannot be negative"); + if(maxRedirects > MAX_REDIRECTS) + throw new IllegalArgumentException("Max redirect cannot exceed " + MAX_REDIRECTS); + + this.maxRedirects = maxRedirects; + this.shouldRedirect = shouldRedirect != null ? shouldRedirect : DEFAULT_SHOULD_REDIRECT; + } + + /* + * @return max redirects + */ + public int maxRedirects() { + return this.maxRedirects; + } + + /* + * @return should redirect + */ + public IShouldRedirect shouldRedirect() { + return this.shouldRedirect; + } +} From 4cb303162cebef0ce7c558c3e8cdbd3eea7df68f Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:05:50 +0530 Subject: [PATCH 04/10] Migrated batching to OkHttp --- .../graph/content/MSBatchRequestContent.java | 51 +++------ .../graph/content/MSBatchResponseContent.java | 74 +++++++++--- .../content/MSBatchRequestContentTest.java | 105 +++++++++--------- .../content/MSBatchResponseContentTest.java | 54 +++++++-- 4 files changed, 169 insertions(+), 115 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index b944f9e32..877a6ecca 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -7,21 +7,20 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import com.microsoft.graph.httpcore.RequestSerializer; + import okhttp3.Headers; -import okhttp3.Request; import okhttp3.RequestBody; -import okio.Buffer; public class MSBatchRequestContent { private Map batchRequestStepsHashMap; - private final int maxNumberOfRequests = 20; + public static final int MAX_NUMBER_OF_REQUESTS = 20; public MSBatchRequestContent(List batchRequestStepsArray) { - if(batchRequestStepsArray.size() > maxNumberOfRequests) - throw new IllegalArgumentException("Number of batch request steps cannot exceed 20."); + if(batchRequestStepsArray.size() > MAX_NUMBER_OF_REQUESTS) + throw new IllegalArgumentException("Number of batch request steps cannot exceed " + MAX_NUMBER_OF_REQUESTS); this.batchRequestStepsHashMap = new HashMap<>(); for(MSBatchRequestStep requestStep: batchRequestStepsArray) @@ -57,20 +56,24 @@ public String getBatchRequestContent() { JSONObject batchRequestContentMap = new JSONObject(); JSONArray batchContentArray = new JSONArray(); for(Map.Entry requestStep : batchRequestStepsHashMap.entrySet()) { - batchContentArray.add(getBatchRequestMapFromRequestStep(requestStep.getValue())); + batchContentArray.add(getBatchRequestObjectFromRequestStep(requestStep.getValue())); } batchRequestContentMap.put("requests", batchContentArray); - return batchRequestContentMap.toJSONString(); + + String content = batchRequestContentMap.toString(); + return content; } @SuppressWarnings("unchecked") - private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep batchRequestStep){ + private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep batchRequestStep){ JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); String url = batchRequestStep.getRequest().url().toString(); - url = url.replaceAll("https://graph.microsoft.com/v1.0", ""); - url = url.replace("https://graph.microsoft.com/beta", ""); + url = url.replaceAll("https://graph.microsoft.com/v1.0/", ""); + url = url.replaceAll("http://graph.microsoft.com/v1.0/", ""); + url = url.replaceAll("https://graph.microsoft.com/beta/", ""); + url = url.replaceAll("http://graph.microsoft.com/beta/", ""); contentmap.put("url", url); contentmap.put("method", batchRequestStep.getRequest().method().toString()); @@ -79,7 +82,7 @@ private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep ba if(headers != null && headers.size() != 0) { JSONObject headerMap = new JSONObject(); for(Map.Entry> entry : headers.toMultimap().entrySet()) { - headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); + headerMap.put(entry.getKey(), RequestSerializer.getHeaderValuesAsString(entry.getValue())); } contentmap.put("headers", headerMap); } @@ -94,34 +97,12 @@ private JSONObject getBatchRequestMapFromRequestStep(final MSBatchRequestStep ba RequestBody body = batchRequestStep.getRequest().body(); if(body != null) { try { - contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); + contentmap.put("body", RequestSerializer.requestBodyToJSONObject(batchRequestStep.getRequest())); }catch(IOException | ParseException e) { e.printStackTrace(); } } - return contentmap; } - private String getHeaderValuesAsString(final List list) { - StringBuilder builder = new StringBuilder(""); - if(list.size() != 0) { - builder.append(list.get(0)); - for(int i=1;i batchRequestsHashMap; + private JSONArray batchResponseArray; - public MSBatchResponseContent(String batchResponseData) { - JSONParser parser = new JSONParser(); - try { - if(batchResponseData != null) - batchResponseObj = (JSONObject) parser.parse(batchResponseData); - } - catch(ParseException e) { - e.printStackTrace(); + public MSBatchResponseContent(Response batchResponse) { + if(batchResponse == null) + throw new IllegalArgumentException("Batch Response cannot be null"); + + this.batchRequestsHashMap = RequestSerializer.createBatchRequestsHashMap(batchResponse); + this.batchResponse = batchResponse; + if(batchResponse.body() != null) { + try { + String batchResponseData = batchResponse.body().string(); + if(batchResponseData != null) { + batchResponseObj = RequestSerializer.stringToJSONObject(batchResponseData); + if(batchResponseObj != null) { + batchResponseArray = (JSONArray)batchResponseObj.get("responses"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } } } @@ -32,28 +49,39 @@ public Response getResponseById(String requestId) { if(responses == null) return null; - for(Object response: responses) { + for(Object response : responses) { JSONObject jsonresponse = (JSONObject)response; String id = (String)jsonresponse.get("id"); if(id.compareTo(requestId) == 0) { Response.Builder builder = new Response.Builder(); + // Put corresponding request into the constructed response + builder.request(batchRequestsHashMap.get(requestId)); + // copy protocol and message same as of batch response + builder.protocol(batchResponse.protocol()); + builder.message(batchResponse.message()); + + // Put status code of the corresponding request in JSONArray if(jsonresponse.get("status") != null) { - String status = (String)jsonresponse.get("status"); - builder.code(Integer.parseInt(status)); + Long status = (Long)jsonresponse.get("status"); + builder.code(status.intValue()); } + // Put body from response array for corresponding id into constructing response if(jsonresponse.get("body") != null) { - String bodyAsString = (String)jsonresponse.get("body"); + JSONObject jsonObject = (JSONObject)jsonresponse.get("body"); + String bodyAsString = jsonObject.toJSONString(); ResponseBody responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); builder.body(responseBody); } + + // Put headers from response array for corresponding id into constructing response if(jsonresponse.get("headers") != null){ JSONObject jsonheaders = (JSONObject)jsonresponse.get("headers"); for(Object key: jsonheaders.keySet()) { String strkey = (String)key; String strvalue = (String)jsonheaders.get(strkey); - for(String value : strvalue.split("; ")) { + for(String value : strvalue.split(";")) { builder.header(strkey, value); } } @@ -64,9 +92,19 @@ public Response getResponseById(String requestId) { return null; } + /* + * @return responses as a string + */ public String getResponses() { - if(batchResponseObj != null) - return ((JSONArray)batchResponseObj.get("responses")).toJSONString(); - return null; + return batchResponseArray != null ? batchResponseArray.toJSONString() : null; + } + + /* + * @return nextLink of batch response + */ + public String nextLink() { + if(batchResponseObj == null) return null; + Object nextLinkObject = batchResponseObj.get("nextLink"); + return nextLinkObject != null ? ((JSONObject)nextLinkObject).toString() : null; } } diff --git a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java index a4c37813a..ef5835654 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchRequestContentTest.java @@ -11,77 +11,78 @@ public class MSBatchRequestContentTest { - String testurl = "http://graph.microsoft.com"; - + String testurl = "http://graph.microsoft.com/me"; + @Test public void testMSBatchRequestContentCreation() { List requestStepArray = new ArrayList<>(); - for(int i=0;i<5;i++) { - Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); - requestStepArray.add(requestStep); - } - MSBatchRequestContent requestContent = new MSBatchRequestContent(requestStepArray); - assertTrue(requestContent.getBatchRequestContent() != null); + for(int i=0;i<5;i++) { + Request request = new Request.Builder().url(testurl).build(); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("" + i, request, arrayOfDependsOnIds); + requestStepArray.add(requestStep); + } + MSBatchRequestContent requestContent = new MSBatchRequestContent(requestStepArray); + assertTrue(requestContent.getBatchRequestContent() != null); } - + @Test public void testGetBatchRequestContent() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testGetBatchRequestContentWithHeader() { Request request = new Request.Builder().url(testurl).header("testkey", "testvalue").build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"headers\":\"{\\\"testkey\\\":\\\"testvalue\\\"}\",\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + String content = requestContent.getBatchRequestContent(); + System.out.println(content); + String expectedContent = "{\"requests\":[{\"headers\":{\"testkey\":\"testvalue\"},\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testRemoveBatchRequesStepWithId() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - requestContent.removeBatchRequestStepWithId("1"); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.removeBatchRequestStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[]}"; + assertTrue(content.compareTo(expectedContent) == 0); } - + @Test public void testRemoveBatchRequesStepWithIdByAddingMultipleBatchSteps() { Request request = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds = new ArrayList<>(); - MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); - - Request request1 = new Request.Builder().url(testurl).build(); - List arrayOfDependsOnIds1 = new ArrayList<>(); - arrayOfDependsOnIds1.add("1"); - MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); - - MSBatchRequestContent requestContent = new MSBatchRequestContent(); - requestContent.addBatchRequestStep(requestStep); - requestContent.addBatchRequestStep(requestStep1); - - requestContent.removeBatchRequestStepWithId("1"); - String content = requestContent.getBatchRequestContent(); - String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":\"[]\",\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\"}]}"; - assertTrue(content.compareTo(expectedContent) == 0); + List arrayOfDependsOnIds = new ArrayList<>(); + MSBatchRequestStep requestStep = new MSBatchRequestStep("1", request, arrayOfDependsOnIds); + + Request request1 = new Request.Builder().url(testurl).build(); + List arrayOfDependsOnIds1 = new ArrayList<>(); + arrayOfDependsOnIds1.add("1"); + MSBatchRequestStep requestStep1 = new MSBatchRequestStep("2", request1, arrayOfDependsOnIds1); + + MSBatchRequestContent requestContent = new MSBatchRequestContent(); + requestContent.addBatchRequestStep(requestStep); + requestContent.addBatchRequestStep(requestStep1); + + requestContent.removeBatchRequestStepWithId("1"); + String content = requestContent.getBatchRequestContent(); + String expectedContent = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"http:\\/\\/graph.microsoft.com\\/me\"}]}"; + assertTrue(content.compareTo(expectedContent) == 0); } } diff --git a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java index 1eebc8219..0261889ea 100644 --- a/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java +++ b/src/test/java/com/microsoft/graph/content/MSBatchResponseContentTest.java @@ -1,52 +1,86 @@ package com.microsoft.graph.content; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.IOException; + import org.junit.Test; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.ResponseBody; public class MSBatchResponseContentTest { @Test public void testNullMSBatchResponseContent() { - String responsedata = null; - MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); - assertTrue(batchresponse.getResponses() == null); + Response response = null; + try { + MSBatchResponseContent batchresponse = new MSBatchResponseContent(response); + } + catch(IllegalArgumentException e) { + assertNotNull(e); + } } @Test public void testValidMSBatchResponseContent() { - String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + String responsebody = "{\"responses\": [{\"id\": \"1\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"2\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"3\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"3\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata = TestResponse(responsebody, requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); assertTrue(batchresponse.getResponses() != null); } @Test public void testInvalidMSBatchResponseContentWithEmptyResponse() { - String responsedata = "{\"responses\": [] }"; + String responsebody = "{\"responses\": [] }"; + String requestbody = "{\"requests\":[]}"; + Response responsedata = TestResponse(responsebody, requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); assertTrue(batchresponse.getResponseById("1") == null); } @Test public void testInvalidMSBatchResponseContentWithNullResponseString() { - MSBatchResponseContent batchresponse = new MSBatchResponseContent(null); - assertTrue(batchresponse.getResponseById("1") == null); + try{ + new MSBatchResponseContent(null); + }catch(Exception e) { + assertTrue(e instanceof IllegalArgumentException); + } } @Test public void testInvalidMSBatchResponseContentWithMalformedResponse() { - String invalidResponsedata = "{responses: [] }"; + String invalidResponsebody = "{responses: [] }"; + String requestbody = "{requests:[]}"; + Response invalidResponsedata = TestResponse(invalidResponsebody, requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(invalidResponsedata); assertTrue(batchresponse.getResponses() == null); } @Test - public void testGetMSBatchResponseContentByID() { - String responsedata = "{\"responses\": [{ \"id\": \"1\", \"status\": 302, \"headers\": { \"location\": \"https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi\" } }, { \"id\": \"3\", \"status\": 401, \"body\": { \"error\": { \"code\": \"Forbidden\", \"message\": \"...\" } } }, { \"id\": \"2\", \"status\": 200, \"body\": { \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)\", \"value\": [] } }, { \"id\": \"4\", \"status\": 204, \"body\": null } ] }"; + public void testGetMSBatchResponseContentByID() throws IOException { + String responsebody = "{\"responses\": [{\"id\": \"1\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"businessPhones\":[\"8006427676\"],\"displayName\":\"MOD Administrator\",\"givenName\":\"MOD\",\"jobTitle\":null,\"mail\":\"admin@M365x751487.OnMicrosoft.com\",\"mobilePhone\":\"425-882-1032\",\"officeLocation\":null,\"preferredLanguage\":\"en-US\",\"surname\":\"Administrator\",\"userPrincipalName\":\"admin@M365x751487.onmicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\"}},{\"id\": \"2\",\"status\":200,\"headers\" : {\"Cache-Control\":\"no-store, no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#drives/$entity\",\"createdDateTime\":\"2019-01-12T09:05:38Z\",\"description\":\"\",\"id\":\"b!nlu9o5I9g0y8gsHXfUM_bPTZ0oM_wVNArHM5R4-VkHLlnxx5SpqHRJledwfICP9f\",\"lastModifiedDateTime\":\"2019-03-06T06:59:04Z\",\"name\":\"OneDrive\",\"webUrl\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents\",\"driveType\":\"business\",\"createdBy\":{\"user\":{\"displayName\":\"System Account\"}},\"lastModifiedBy\":{\"user\":{\"displayName\":\"System Account\"}},\"owner\":{\"user\":{\"email\":\"admin@M365x751487.OnMicrosoft.com\",\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"quota\":{\"deleted\":0,\"remaining\":1099509670098,\"state\":\"normal\",\"total\":1099511627776,\"used\":30324}}},{\"id\": \"3\",\"status\":201,\"headers\" : {\"Location\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"Preference-Applied\":\"odata.include-annotations=*\",\"Cache-Control\":\"no-cache\",\"OData-Version\":\"4.0\",\"Content-Type\":\"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\"},\"body\":{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c')/onenote/notebooks/$entity\",\"id\":\"1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"self\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0\",\"createdDateTime\":\"2019-03-06T08:08:09Z\",\"displayName\":\"My Notebook -442293399\",\"lastModifiedDateTime\":\"2019-03-06T08:08:09Z\",\"isDefault\":false,\"userRole\":\"Owner\",\"isShared\":false,\"sectionsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sections\",\"sectionGroupsUrl\":\"https://graph.microsoft.com/v1.0/users/6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c/onenote/notebooks/1-94e4376a-a1c1-441a-8b41-af5c86ee39d0/sectionGroups\",\"createdBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"lastModifiedBy\":{\"user\":{\"id\":\"6b4fa8ea-7e6e-486e-a8f4-d00a5b23488c\",\"displayName\":\"MOD Administrator\"}},\"links\":{\"oneNoteClientUrl\":{\"href\":\"onenote:https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"},\"oneNoteWebUrl\":{\"href\":\"https://m365x751487-my.sharepoint.com/personal/admin_m365x751487_onmicrosoft_com/Documents/Notebooks/My%20Notebook%20-442293399\"}}}}]}"; + String requestbody = "{\"requests\":[{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"1\",\"url\":\"me\"},{\"method\":\"GET\",\"dependsOn\":[],\"id\":\"2\",\"url\":\"me\\/drive\"},{\"headers\":{\"content-type\":\"application\\/json\"},\"method\":\"POST\",\"dependsOn\":[],\"id\":\"3\",\"body\":{\"displayName\":\"My Notebook -1263732088\"},\"url\":\"me\\/onenote\\/notebooks\"}]}"; + Response responsedata = TestResponse(responsebody,requestbody); MSBatchResponseContent batchresponse = new MSBatchResponseContent(responsedata); Response response = batchresponse.getResponseById("1"); assertTrue(response != null); } + + private Response TestResponse(String responsebody, String requestbody) { + Response.Builder builder = new Response.Builder(); + builder.body(ResponseBody.create(MediaType.parse("application/json"), responsebody)); + Request request = new Request.Builder().url("https://graph.microsoft.com/").method("POST", RequestBody.create(MediaType.parse("application/json"), requestbody)).build(); + builder.request(request); + builder.protocol(Protocol.HTTP_1_0); + builder.code(200); + builder.message("test message"); + return builder.build(); + } } From ce595eb65d3c4e3202b5619a0f1691a0011f287d Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 13:06:50 +0530 Subject: [PATCH 05/10] Migrated redirect, retry handlers and retry options to okhttp --- .../graph/httpcore/RedirectHandler.java | 58 ++++++-- .../graph/httpcore/RetryHandler.java | 131 +++++++++++------- .../middlewareoption/IShouldRetry.java | 2 +- .../middlewareoption/RetryOptions.java | 63 ++++++++- 4 files changed, 187 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 093d90115..927ed873e 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -9,26 +9,47 @@ import java.io.IOException; import java.net.ProtocolException; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; + import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.Request; -import okhttp3.RequestBody; import okhttp3.Response; -import okhttp3.internal.http.HttpMethod; public class RedirectHandler implements Interceptor{ - public static final RedirectHandler INSTANCE = new RedirectHandler(); - final int maxRedirect = 5; + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.REDIRECT; - public boolean isRedirected(Request request, Response response, int redirectCount) throws IOException { - - if(redirectCount > maxRedirect) return false; + private RedirectOptions mRedirectOptions; + + /* + * Initialize using default redirect options, default IShouldRedirect and max redirect value + */ + public RedirectHandler() { + this.mRedirectOptions = new RedirectOptions(); + } + + /* + * @param redirectOptions pass instance of redirect options to be used + */ + public RedirectHandler(RedirectOptions redirectOptions) { + this.mRedirectOptions = redirectOptions; + if(redirectOptions == null) { + this.mRedirectOptions = new RedirectOptions(); + } + } + + public boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { + // Check max count of redirects reached + if(redirectCount > redirectOptions.maxRedirects()) return false; + // Location header empty then don't redirect final String locationHeader = response.header("location"); if(locationHeader == null) return false; + // If any of 301,302,303,307,308 then redirect final int statusCode = response.code(); if(statusCode == HTTP_PERM_REDIRECT || //308 statusCode == HTTP_MOVED_PERM || //301 @@ -46,12 +67,15 @@ public Request getRedirect( String location = userResponse.header("Location"); if (location == null) return null; + // TODO: If Location header is relative reference then final URL should be relative to original target URL. + HttpUrl requestUrl = userResponse.request().url(); HttpUrl locationUrl = userResponse.request().url().resolve(location); + // Don't follow redirects to unsupported protocols. if (locationUrl == null) return null; - + // Most redirects don't include a request body. Request.Builder requestBuilder = userResponse.request().newBuilder(); @@ -63,25 +87,37 @@ public Request getRedirect( if (!sameScheme || !sameHost) { requestBuilder.removeHeader("Authorization"); } + + // Response status code 303 See Other then POST changes to GET + if(userResponse.code() == HTTP_SEE_OTHER) { + requestBuilder.method("GET", null); + } return requestBuilder.url(locationUrl).build(); } + // Intercept request and response made to network @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = null; - int redirectCount = 1; + int requestsCount = 1; + + // Use should retry pass along with this request + RedirectOptions redirectOptions = request.tag(RedirectOptions.class); + redirectOptions = redirectOptions != null ? redirectOptions : this.mRedirectOptions; + while(true) { response = chain.proceed(request); - boolean shouldRedirect = isRedirected(request, response, redirectCount); + boolean shouldRedirect = redirectOptions.shouldRedirect().shouldRedirect(response) + && isRedirected(request, response, requestsCount, redirectOptions); if(!shouldRedirect) break; Request followup = getRedirect(request, response); if(followup == null) break; request = followup; - redirectCount++; + requestsCount++; } return response; } diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 237dfed87..2a4246545 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -2,6 +2,9 @@ import java.io.IOException; +import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; import okhttp3.Interceptor; @@ -9,86 +12,112 @@ import okhttp3.Response; public class RetryHandler implements Interceptor{ + + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.RETRY; - /** - * Maximum number of allowed retries if the server responds with a HTTP code - * in our retry code list. Default value is 1. - */ - private final int maxRetries = 2; - - /** - * Retry interval between subsequent requests, in milliseconds. Default - * value is 1 second. + private RetryOptions mRetryOption; + + /* + * constant string being used */ - private long retryInterval = 1000; - private final int DELAY_MILLISECONDS = 1000; + private final String RETRY_ATTEMPT_HEADER = "Retry-Attempt"; private final String RETRY_AFTER = "Retry-After"; private final String TRANSFER_ENCODING = "Transfer-Encoding"; + private final String TRANSFER_ENCODING_CHUNKED = "chunked"; + private final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + private final String CONTENT_TYPE = "Content-Type"; + + public static final int MSClientErrorCodeTooManyRequests = 429; + public static final int MSClientErrorCodeServiceUnavailable = 503; + public static final int MSClientErrorCodeGatewayTimeout = 504; - private final int MSClientErrorCodeTooManyRequests = 429; - private final int MSClientErrorCodeServiceUnavailable = 503; - private final int MSClientErrorCodeGatewayTimeout = 504; - private final RetryOptions mRetryOption; + private final long DELAY_MILLISECONDS = 1000; - public RetryHandler(RetryOptions option) { - super(); - this.mRetryOption = option; + /* + * @retryOption Create Retry handler using retry option + */ + public RetryHandler(RetryOptions retryOption) { + this.mRetryOption = retryOption; + if(this.mRetryOption == null) { + this.mRetryOption = new RetryOptions(); + } } - + /* + * Initialize retry handler with default retry option + */ public RetryHandler() { this(null); } - public boolean retryRequest(Response response, int executionCount, Request request) { + private boolean retryRequest(Response response, int executionCount, Request request, RetryOptions retryOptions) { - RetryOptions retryOption = request.tag(RetryOptions.class); - if(retryOption != null) { - return retryOption.shouldRetry().shouldRetry(response, executionCount, request); + // Should retry option + // Use should retry common for all requests + IShouldRetry shouldRetryCallback = null; + if(retryOptions != null) { + shouldRetryCallback = retryOptions.shouldRetry(); } - if(mRetryOption != null) { - return mRetryOption.shouldRetry().shouldRetry(response, executionCount, request); + // Call should retry callback + if(shouldRetryCallback != null) { + shouldRetryCallback.shouldRetry(response, executionCount, request, retryOptions.delay()); } boolean shouldRetry = false; + // Status codes 429 503 504 int statusCode = response.code(); - shouldRetry = (executionCount < maxRetries) && checkStatus(statusCode) && isBuffered(response, request); + // Only requests with payloads that are buffered/rewindable are supported. + // Payloads with forward only streams will be have the responses returned + // without any retry attempt. + shouldRetry = (executionCount <= retryOptions.maxRetries()) && checkStatus(statusCode) && isBuffered(response, request); if(shouldRetry) { - String retryAfterHeader = response.header(RETRY_AFTER); - if(retryAfterHeader != null) - retryInterval = Long.parseLong(retryAfterHeader); - else - retryInterval = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + long retryInterval = getRetryAfter(response, retryOptions.delay(), executionCount); + try { + Thread.sleep(retryInterval); + } catch (InterruptedException e) { + e.printStackTrace(); + } } return shouldRetry; } - - public long getRetryInterval() { - return retryInterval; + + private long getRetryAfter(Response response, long delay, int executionCount) { + String retryAfterHeader = response.header(RETRY_AFTER); + long retryDelay = RetryOptions.DEFAULT_DELAY; + if(retryAfterHeader != null) { + retryDelay = Long.parseLong(retryAfterHeader); + } else { + retryDelay = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + retryDelay = executionCount < 2 ? retryDelay : retryDelay + delay + (long)Math.random(); + } + return Math.min(retryDelay, RetryOptions.MAX_DELAY); } private boolean checkStatus(int statusCode) { - if (statusCode == MSClientErrorCodeTooManyRequests || statusCode == MSClientErrorCodeServiceUnavailable - || statusCode == MSClientErrorCodeGatewayTimeout) - return true; - return false; + return (statusCode == MSClientErrorCodeTooManyRequests || statusCode == MSClientErrorCodeServiceUnavailable + || statusCode == MSClientErrorCodeGatewayTimeout); } private boolean isBuffered(Response response, Request request) { String methodName = request.method(); + if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE")) + return true; boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || methodName.equalsIgnoreCase("PUT") || methodName.equalsIgnoreCase("PATCH"); - //Header transferEncoding = response.getFirstHeader(TRANSFER_ENCODING); - String transferEncoding = response.header(TRANSFER_ENCODING); - boolean isTransferEncodingChunked = (transferEncoding != null) && - transferEncoding.equalsIgnoreCase("chunked"); - - if(request.body() != null && isHTTPMethodPutPatchOrPost && isTransferEncodingChunked) - return false; - return true; + if(isHTTPMethodPutPatchOrPost) { + boolean isStream = response.header(CONTENT_TYPE)!=null && response.header(CONTENT_TYPE).equalsIgnoreCase(APPLICATION_OCTET_STREAM); + if(!isStream) { + String transferEncoding = response.header(TRANSFER_ENCODING); + boolean isTransferEncodingChunked = (transferEncoding != null) && + transferEncoding.equalsIgnoreCase(TRANSFER_ENCODING_CHUNKED); + if(request.body() != null && isTransferEncodingChunked) + return true; + } + } + return false; } @Override @@ -96,8 +125,14 @@ public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); - int executionCount = 0; - while(retryRequest(response, executionCount, request)) { + + // Use should retry pass along with this request + RetryOptions retryOption = request.tag(RetryOptions.class); + retryOption = retryOption != null ? retryOption : this.mRetryOption; + + int executionCount = 1; + while(retryRequest(response, executionCount, request, retryOption)) { + request = request.newBuilder().addHeader(RETRY_ATTEMPT_HEADER, String.valueOf(executionCount)).build(); executionCount++; response = chain.proceed(request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index 366c310a6..0eeb9b684 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -4,5 +4,5 @@ import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(Response response, int executionCount, Request request); + boolean shouldRetry(Response response, int executionCount, Request request, long delay); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index 57ccfbc29..4714a4c8f 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -5,20 +5,69 @@ public class RetryOptions implements IMiddlewareControl { private IShouldRetry shouldretry; + public static final IShouldRetry DEFAULT_SHOULD_RETRY = new IShouldRetry() { + @Override + public boolean shouldRetry(Response response, int executionCount, Request request, long delay) { + return true; + } + }; + private int maxRetries; + public static final int MAX_RETRIES = 10; + public static final int DEFAULT_MAX_RETRIES = 3; + + /* + * Delay in seconds + */ + private long delay; + public static final long DEFAULT_DELAY = 3; // 3 seconds default delay + public static final long MAX_DELAY = 180; // 180 second max delay + + /* + * Create default instance of retry options, with default values of delay, max retries and shouldRetry callback. + */ public RetryOptions(){ - this(new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, Request request) { - return true; - } - }); + this(DEFAULT_SHOULD_RETRY, DEFAULT_MAX_RETRIES, DEFAULT_DELAY); } - public RetryOptions(IShouldRetry shouldretry){ - this.shouldretry = shouldretry; + /* + * @param shouldRetry Retry callback to be called before making a retry + * @param maxRetries Number of max retires for a request + * @param delay Delay in seconds between retries + */ + public RetryOptions(IShouldRetry shouldRetry, int maxRetries, long delay) { + if(delay > MAX_DELAY) + throw new IllegalArgumentException("Delay cannot exceed " + MAX_DELAY); + if(delay < 0) + throw new IllegalArgumentException("Delay cannot be negative"); + if(maxRetries > MAX_RETRIES) + throw new IllegalArgumentException("Max retires cannot exceed " + MAX_RETRIES); + if(maxRetries < 0) + throw new IllegalArgumentException("Max retires cannot be negative"); + + this.shouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; + this.maxRetries = maxRetries; + this.delay = delay; } + /* + * @return should retry callback + */ public IShouldRetry shouldRetry() { return shouldretry; } + + /* + * @return Number of max retries + */ + public int maxRetries() { + return maxRetries; + } + + /* + * @return Delay in seconds between retries + */ + public long delay() { + return delay; + } } From c6f788600511e7fe8c91de47b3107bb71f178f34 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Thu, 7 Mar 2019 17:55:56 +0530 Subject: [PATCH 06/10] Migrated HttpClient and tests to okhttp --- .../graph/httpcore/AuthenticationHandler.java | 4 + .../microsoft/graph/httpcore/HttpClients.java | 1 + .../graph/httpcore/RequestSerializer.java | 117 ++++++++ .../graph/httpcore/RetryHandler.java | 16 +- .../middlewareoption/HttpContextBuilder.java | 33 --- .../middlewareoption/RetryOptions.java | 22 +- .../httpcore/AuthenticationHandlerTest.java | 23 +- .../graph/httpcore/RedirectHandlerTest.java | 263 +++++++++--------- .../graph/httpcore/RetryHandlerTest.java | 163 +++++------ 9 files changed, 368 insertions(+), 274 deletions(-) create mode 100644 src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java delete mode 100644 src/main/java/com/microsoft/graph/httpcore/middlewareoption/HttpContextBuilder.java diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index b7eb1003c..ad1992eb6 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -2,11 +2,15 @@ import java.io.IOException; +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; + import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class AuthenticationHandler implements Interceptor { + + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.AUTHENTICATION; private IAuthenticationProvider authProvider; diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index dc5ddbdba..376f8a660 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -22,6 +22,7 @@ public static Builder custom() { */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) + .followRedirects(false) .addInterceptor(new RetryHandler()) .addInterceptor(new RedirectHandler()) .build(); diff --git a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java new file mode 100644 index 000000000..917159d38 --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java @@ -0,0 +1,117 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; + +public class RequestSerializer { + + public static Map createBatchRequestsHashMap(Response batchResponse) { + if(batchResponse == null)return null; + try { + Map batchRequestsHashMap = new HashMap<>(); + JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); + JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); + for(Object item : requestArray) { + JSONObject requestObject = (JSONObject)item; + + Request.Builder builder = new Request.Builder(); + + if(requestObject.get("url") != null) { + StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); + fullUrl.append(requestObject.get("url").toString()); + builder.url(fullUrl.toString()); + } + if(requestObject.get("headers") != null) { + JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); + for(Object key: jsonheaders.keySet()) { + String strkey = (String)key; + String strvalue = (String)jsonheaders.get(strkey); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } + } + } + if(requestObject.get("body") != null) { + JSONObject jsonObject = (JSONObject)requestObject.get("body"); + String bodyAsString = jsonObject.toJSONString(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.method(requestObject.get("method").toString(), requestBody); + } else { + builder.method(requestObject.get("method").toString(), null); + } + batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); + } + return batchRequestsHashMap; + + } catch (IOException | ParseException e) { e.printStackTrace(); } + return null; + } + + /* + * Convert request body to JSONObject + */ + public static JSONObject requestToJSONObject(final Request request) throws IOException, ParseException{ + Request copy = request.newBuilder().build(); + Buffer buffer = new Buffer(); + copy.body().writeTo(buffer); + String body = buffer.readUtf8(); + JSONObject json = (JSONObject)new JSONParser().parse(body); + return json; + } + + /* + * Converts String to JSONObject + */ + public static JSONObject stringToJSONObject(String input) { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = null; + try { + if(input != null) { + jsonObject = (JSONObject) parser.parse(input); + } + } + catch(Exception e) { + e.printStackTrace(); + } + return jsonObject; + } + + /* + * @param list List of parameters of a single header + * @return List of headers to a String seperated by "; " + */ + public static String getHeaderValuesAsString(final List list) { + if(list == null || list.size() == 0)return ""; + StringBuilder builder = new StringBuilder(list.get(0)); + for(int i=1;i MAX_RETRIES) - throw new IllegalArgumentException("Max retires cannot exceed " + MAX_RETRIES); + throw new IllegalArgumentException("Max retries cannot exceed " + MAX_RETRIES); if(maxRetries < 0) - throw new IllegalArgumentException("Max retires cannot be negative"); + throw new IllegalArgumentException("Max retries cannot be negative"); - this.shouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; - this.maxRetries = maxRetries; - this.delay = delay; + this.mShouldretry = shouldRetry != null ? shouldRetry : DEFAULT_SHOULD_RETRY; + this.mMaxRetries = maxRetries; + this.mDelay = delay; } /* * @return should retry callback */ public IShouldRetry shouldRetry() { - return shouldretry; + return mShouldretry; } /* * @return Number of max retries */ public int maxRetries() { - return maxRetries; + return mMaxRetries; } /* * @return Delay in seconds between retries */ public long delay() { - return delay; + return mDelay; } } diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index a0bfccbb6..e6d6eeea6 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -3,16 +3,13 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.IOException; - -import org.apache.http.HttpException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.protocol.HttpClientContext; +import org.junit.Ignore; import org.junit.Test; import okhttp3.Request; -import okhttp3.internal.http2.Header; +import okhttp3.internal.http.RealInterceptorChain; +@Ignore public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; @@ -29,13 +26,17 @@ public void testAuthenticationHandler() { AuthProvider authProvider = new AuthProvider(); AuthenticationHandler authHandler = new AuthenticationHandler(authProvider); Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me/").build(); - HttpClientContext localContext = HttpClientContext.create(); + + RealInterceptorChain chain = new RealInterceptorChain(null, null, null, null, 0, request, null, null, 0, 0, 0); try { - authHandler.process(httpget, localContext); - Header header = httpget.getFirstHeader("Authorization"); - assertTrue(header.getValue().equals("Bearer " + token)); - } catch (HttpException | IOException e) { + authHandler.intercept(chain); + + String value = request.header("Authorization"); + assertTrue(value.equals("Bearer " + token)); + + + } catch (Exception e) { e.printStackTrace(); fail("Authentication handler failure"); } diff --git a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java index f53fe097b..3182b850f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RedirectHandlerTest.java @@ -3,22 +3,20 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; +import java.net.HttpURLConnection; import java.net.ProtocolException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.message.BasicHttpResponse; import org.junit.Test; +import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; + +import okhttp3.MediaType; +import okhttp3.Protocol; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; -import okhttp3.internal.http2.Header; +import okhttp3.internal.http.StatusLine; public class RedirectHandlerTest { @@ -27,112 +25,110 @@ public class RedirectHandlerTest { String differenthosturl = "https://graph.abc.com/v1.0/"; @Test - public void testIsRedirectedFailureByNoLocationHeader() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedFailureByNoLocationHeader() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(!isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedFailure failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(!isRedirected); } @Test - public void testIsRedirectedFailureByStatusCodeBadRequest() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedFailureByStatusCodeBadRequest() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_REQUEST, "Bad Request"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(!isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedFailure1 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_BAD_REQUEST) + .message( "Bad Request") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(!isRedirected); } @Test - public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeMovedTemporarily() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(isRedirected); } @Test - public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeMovedPermanently() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_PERMANENTLY, "Moved Permanently"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess1 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_PERM) + .message("Moved Permanently") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response, 0, new RedirectOptions()); + assertTrue(isRedirected); } - + @Test - public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httpget = new HttpGet(testmeurl); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_TEMPORARY_REDIRECT, "Temporary Redirect"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess2 failure"); - } + public void testIsRedirectedSuccessWithStatusCodeTemporaryRedirect() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(StatusLine.HTTP_TEMP_REDIRECT) + .message("Temporary Redirect") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response,0,new RedirectOptions()); + assertTrue(isRedirected); } - + @Test - public void testIsRedirectedSuccessWithStatusCodeSeeOther() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + public void testIsRedirectedSuccessWithStatusCodeSeeOther() throws IOException { + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testmeurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); - try { - boolean isRedirected = redirectHandler.isRedirected(httpget, response, localContext); - assertTrue(isRedirected); - } catch (ProtocolException e) { - e.printStackTrace(); - fail("Redirect handler testIsRedirectedSuccess3 failure"); - } + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message( "See Other") + .addHeader("location", testmeurl) + .request(httpget) + .build(); + boolean isRedirected = redirectHandler.isRedirected(httpget, response,0,new RedirectOptions()); + assertTrue(isRedirected); } @Test public void testGetRedirectForGetMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + RedirectHandler redirectHandler = new RedirectHandler(); Request httpget = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httpget) + .build(); try { - Request request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForGetMethod failure"); @@ -141,18 +137,22 @@ public void testGetRedirectForGetMethod() { @Test public void testGetRedirectForGetMethodForAuthHeader() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httpget = new Request.Builder().url(testurl).build(); - httpget.addHeader("Authorization", "TOKEN"); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", differenthosturl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + Request httpget = new Request.Builder().url(testurl).header("Authorization", "TOKEN").build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", differenthosturl) + .request(httpget) + .build(); + try { - Request request = redirectHandler.getRedirect(httpget, response, localContext); + Request request = redirectHandler.getRedirect(httpget, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); - Header header = request.getFirstHeader("Authorization"); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); + String header = request.header("Authorization"); assertTrue(header == null); } catch (ProtocolException e) { e.printStackTrace(); @@ -162,16 +162,20 @@ public void testGetRedirectForGetMethodForAuthHeader() { @Test public void testGetRedirectForHeadMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - HttpHead httphead = new HttpHead(testurl); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + Request httphead = new Request.Builder().url(testurl).method("HEAD", null).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httphead) + .build(); try { - Request request = redirectHandler.getRedirect(httphead, response, localContext); + Request request = redirectHandler.getRedirect(httphead, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpHead.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("HEAD")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForHeadMethod failure"); @@ -180,16 +184,21 @@ public void testGetRedirectForHeadMethod() { @Test public void testGetRedirectForPostMethod() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; - Request httppost = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + RedirectHandler redirectHandler = new RedirectHandler(); + RequestBody body = RequestBody.create(MediaType.parse("application/json"),""); + Request httppost = new Request.Builder().url(testurl).post(body).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_MOVED_TEMP) + .message("Moved Temporarily") + .addHeader("location", testmeurl) + .request(httppost) + .build(); try { - Request request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpPost.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("POST")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForPostMethod failure"); @@ -198,16 +207,22 @@ public void testGetRedirectForPostMethod() { @Test public void testGetRedirectForPostMethodWithStatusCodeSeeOther() { - RedirectHandler redirectHandler = RedirectHandler.INSTANCE; + RedirectHandler redirectHandler = new RedirectHandler(); Request httppost = new Request.Builder().url(testurl).build(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"); - response.setHeader("location", testmeurl); - HttpClientContext localContext = HttpClientContext.create(); + + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_SEE_OTHER) + .message("See Other") + .addHeader("location", testmeurl) + .request(httppost) + .build(); + try { - Request request = redirectHandler.getRedirect(httppost, response, localContext); + Request request = redirectHandler.getRedirect(httppost, response); assertTrue(request != null); - final String method = request.getRequestLine().getMethod(); - assertTrue(method.equalsIgnoreCase(HttpGet.METHOD_NAME)); + final String method = request.method(); + assertTrue(method.equalsIgnoreCase("GET")); } catch (ProtocolException e) { e.printStackTrace(); fail("Redirect handler testGetRedirectForPostMethod1 failure"); diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 06299fe1f..691b9fd75 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -1,139 +1,128 @@ package com.microsoft.graph.httpcore; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; import javax.xml.ws.spi.http.HttpContext; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.protocol.HttpCoreContext; import org.junit.Test; import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; +import okhttp3.MediaType; +import okhttp3.Protocol; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.internal.http.StatusLine; public class RetryHandlerTest { - - int maxRetries = 2; - int retryInterval = 1000; - String testurl = "https://graph.microsoft.com/v1.0/"; + + int maxRetries = 2; + int retryInterval = 1000; + String testmeurl = "https://graph.microsoft.com/v1.0/me"; @Test public void testRetryHandlerCreation() { RetryHandler retryhandler = new RetryHandler(); - assertTrue(retryhandler.getRetryInterval() == retryInterval); + assertNotNull(retryhandler); } - + @Test public void testRetryHandlerWithRetryOptions() { RetryOptions option = new RetryOptions(); RetryHandler retryhandler = new RetryHandler(option); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + assertTrue(retryhandler.retryRequest(response, 1, httpget, option)); } - + @Test public void testRetryHandlerWithCustomRetryOptions() { - RetryOptions option = new RetryOptions(new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, HttpContext context) { + IShouldRetry shouldRetry = new IShouldRetry() { + public boolean shouldRetry(Response response, int executionCount, Request request, long delay){ return false; } - }); + }; + RetryOptions option = new RetryOptions(shouldRetry, 5, 0); RetryHandler retryhandler = new RetryHandler(option); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertTrue(!retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + assertTrue(!retryhandler.retryRequest(response, 0, httpget, option)); } - + @Test public void testRetryRequestWithMaxRetryAttempts() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout"); - HttpClientContext localContext = HttpClientContext.create(); - assertFalse(retryhandler.retryRequest(response, 3, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message("Gateway Timeout") + .request(httpget) + .build(); + // Default retry options with Number of maxretries default to 3 + RetryOptions retryOptions = new RetryOptions(); + // Try to execute one more than allowed default max retries + int executionCount = RetryOptions.DEFAULT_MAX_RETRIES + 1; + assertFalse(retryhandler.retryRequest(response, executionCount, httpget, retryOptions)); } - + @Test public void testRetryRequestForStatusCode() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); - HttpClientContext localContext = HttpClientContext.create(); - assertFalse(retryhandler.retryRequest(response, 1, localContext)); + Request httpget = new Request.Builder().url(testmeurl).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + // For status code 500 which is not in (429 503 504), So NO retry + .code(HttpURLConnection.HTTP_SERVER_ERROR) + .message( "Internal Server Error") + .request(httpget) + .build(); + assertFalse(retryhandler.retryRequest(response, 1, httpget, new RetryOptions())); } - + @Test public void testRetryRequestWithTransferEncoding() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - response.setHeader("Transfer-Encoding", "chunked"); - Request httppost = new Request.Builder().url(testurl).build(); - - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertFalse(retryhandler.retryRequest(response, 1, localContext)); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequest3 test failure"); - } + Request httppost = new Request.Builder().url(testmeurl).post(RequestBody.create(MediaType.parse("application/json"), "TEST")).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message( "gateway timeout") + .request(httppost) + .addHeader("Transfer-Encoding", "chunked") + .build(); + assertTrue(retryhandler.retryRequest(response, 1, httppost, new RetryOptions())); } - + @Test public void testRetryRequestWithExponentialBackOff() { RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - Request httppost = new Request.Builder().url(testurl).build(); - - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); - assertTrue(retryhandler.getRetryInterval() == 2000); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequest3 test failure"); - } - } - - @Test - public void testRetryHandlerRetryRequestWithRetryAfterHeader() { - RetryHandler retryhandler = new RetryHandler(); - Response response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Internal Server Error"); - response.setHeader("Retry-After", "100"); - Request httppost = new Request.Builder().url(testurl).build(); + Request httppost = new Request.Builder().url(testmeurl).post(RequestBody.create(MediaType.parse("application/json"), "TEST")).build(); + Response response = new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_GATEWAY_TIMEOUT) + .message( "gateway timeout") + .request(httppost) + .addHeader("Transfer-Encoding", "chunked") + .build(); - try { - HttpEntity entity = new StringEntity("TEST"); - httppost.setEntity(entity); - HttpClientContext localContext = HttpClientContext.create(); - localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, httppost); - assertTrue(retryhandler.retryRequest(response, 1, localContext)); - assertTrue(retryhandler.getRetryInterval() == 100); - - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - fail("Retry handler testRetryHandlerRetryRequestWithRetryAfterHeader test failure"); - } + assertTrue(retryhandler.retryRequest(response, 1, httppost, new RetryOptions())); } - } From 339089f88acffb27b4355f8ca4e86bf8a3aa4ceb Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 11:14:03 +0530 Subject: [PATCH 07/10] Added comments and removed suppressed warning --- .../graph/content/MSBatchRequestContent.java | 61 +++++++-- .../graph/content/MSBatchResponseContent.java | 86 ++++++++++++- .../microsoft/graph/httpcore/HttpClients.java | 5 + .../httpcore/IAuthenticationProvider.java | 1 + .../graph/httpcore/RedirectHandler.java | 4 +- .../graph/httpcore/RequestSerializer.java | 117 ------------------ .../graph/httpcore/RetryHandler.java | 1 - .../content/MSBatchResponseContentTest.java | 2 +- .../graph/httpcore/RetryHandlerTest.java | 7 +- 9 files changed, 143 insertions(+), 141 deletions(-) delete mode 100644 src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 877a6ecca..2fd7c5c9a 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -7,17 +7,25 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; -import com.microsoft.graph.httpcore.RequestSerializer; - import okhttp3.Headers; +import okhttp3.Request; import okhttp3.RequestBody; +import okio.Buffer; public class MSBatchRequestContent { private Map batchRequestStepsHashMap; + + // Maximum number of requests that can be sent in a batch public static final int MAX_NUMBER_OF_REQUESTS = 20; + /* + * Creates Batch request content using list provided + * + * @param batchRequestStepsArray List of batch steps for batching + */ public MSBatchRequestContent(List batchRequestStepsArray) { if(batchRequestStepsArray.size() > MAX_NUMBER_OF_REQUESTS) throw new IllegalArgumentException("Number of batch request steps cannot exceed " + MAX_NUMBER_OF_REQUESTS); @@ -27,10 +35,17 @@ public MSBatchRequestContent(List batchRequestStepsArray) { addBatchRequestStep(requestStep); } + /* + * Creates empty batch request content + */ public MSBatchRequestContent() { batchRequestStepsHashMap = new HashMap(); } + /* + * @param batchRequestStep Batch request step adding to batch content + * @return true or false based on addition or no addition of batch request step given + */ public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { if(batchRequestStepsHashMap.containsKey(batchRequestStep.getRequestId())) return false; @@ -38,20 +53,25 @@ public boolean addBatchRequestStep(MSBatchRequestStep batchRequestStep) { return true; } + /* + * @param requestId Id of Batch request step to be removed + * @return true or false based on removal or no removal of batch request step with given id + */ public boolean removeBatchRequestStepWithId(String requestId) { boolean removed = false; if(batchRequestStepsHashMap.containsKey(requestId)) { batchRequestStepsHashMap.remove(requestId); removed = true; - } - for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { - while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)) - removed = true; + for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + } } return removed; } - @SuppressWarnings("unchecked") + /* + * @return Batch request content's json as String + */ public String getBatchRequestContent() { JSONObject batchRequestContentMap = new JSONObject(); JSONArray batchContentArray = new JSONArray(); @@ -60,11 +80,10 @@ public String getBatchRequestContent() { } batchRequestContentMap.put("requests", batchContentArray); - String content = batchRequestContentMap.toString(); + String content = batchRequestContentMap.toString(); return content; } - @SuppressWarnings("unchecked") private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep batchRequestStep){ JSONObject contentmap = new JSONObject(); contentmap.put("id", batchRequestStep.getRequestId()); @@ -82,7 +101,7 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep if(headers != null && headers.size() != 0) { JSONObject headerMap = new JSONObject(); for(Map.Entry> entry : headers.toMultimap().entrySet()) { - headerMap.put(entry.getKey(), RequestSerializer.getHeaderValuesAsString(entry.getValue())); + headerMap.put(entry.getKey(), getHeaderValuesAsString(entry.getValue())); } contentmap.put("headers", headerMap); } @@ -97,7 +116,7 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep RequestBody body = batchRequestStep.getRequest().body(); if(body != null) { try { - contentmap.put("body", RequestSerializer.requestBodyToJSONObject(batchRequestStep.getRequest())); + contentmap.put("body", requestBodyToJSONObject(batchRequestStep.getRequest())); }catch(IOException | ParseException e) { e.printStackTrace(); } @@ -105,4 +124,24 @@ private JSONObject getBatchRequestObjectFromRequestStep(final MSBatchRequestStep return contentmap; } + private String getHeaderValuesAsString(final List list) { + if(list == null || list.size() == 0)return ""; + StringBuilder builder = new StringBuilder(list.get(0)); + for(int i=1;i batchRequestsHashMap; private JSONArray batchResponseArray; + /* + * @param batchResponse OkHttp batch response on execution of batch requests + */ public MSBatchResponseContent(Response batchResponse) { if(batchResponse == null) throw new IllegalArgumentException("Batch Response cannot be null"); - this.batchRequestsHashMap = RequestSerializer.createBatchRequestsHashMap(batchResponse); + this.batchRequestsHashMap = createBatchRequestsHashMap(batchResponse); this.batchResponse = batchResponse; if(batchResponse.body() != null) { try { String batchResponseData = batchResponse.body().string(); if(batchResponseData != null) { - batchResponseObj = RequestSerializer.stringToJSONObject(batchResponseData); + batchResponseObj = stringToJSONObject(batchResponseData); if(batchResponseObj != null) { batchResponseArray = (JSONArray)batchResponseObj.get("responses"); } @@ -41,6 +47,12 @@ public MSBatchResponseContent(Response batchResponse) { } } + /* + * Returns OkHttp Response of given request Id + * + * @param requestId Request Id of batch step + * @return OkHttp Response corresponding to requestId + */ public Response getResponseById(String requestId) { if(batchResponseObj == null) return null; @@ -107,4 +119,70 @@ public String nextLink() { Object nextLinkObject = batchResponseObj.get("nextLink"); return nextLinkObject != null ? ((JSONObject)nextLinkObject).toString() : null; } + + private Map createBatchRequestsHashMap(Response batchResponse) { + if(batchResponse == null)return null; + try { + Map batchRequestsHashMap = new HashMap<>(); + JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); + JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); + for(Object item : requestArray) { + JSONObject requestObject = (JSONObject)item; + + Request.Builder builder = new Request.Builder(); + + if(requestObject.get("url") != null) { + StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); + fullUrl.append(requestObject.get("url").toString()); + builder.url(fullUrl.toString()); + } + if(requestObject.get("headers") != null) { + JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); + for(Object key: jsonheaders.keySet()) { + String strkey = (String)key; + String strvalue = (String)jsonheaders.get(strkey); + for(String value : strvalue.split("; ")) { + builder.header(strkey, value); + } + } + } + if(requestObject.get("body") != null) { + JSONObject jsonObject = (JSONObject)requestObject.get("body"); + String bodyAsString = jsonObject.toJSONString(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); + builder.method(requestObject.get("method").toString(), requestBody); + } else { + builder.method(requestObject.get("method").toString(), null); + } + batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); + } + return batchRequestsHashMap; + + } catch (IOException | ParseException e) { e.printStackTrace(); } + return null; + } + + private JSONObject stringToJSONObject(String input) { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = null; + try { + if(input != null) { + jsonObject = (JSONObject) parser.parse(input); + } + } + catch(Exception e) { + e.printStackTrace(); + } + return jsonObject; + } + + private JSONObject requestBodyToJSONObject(final Request request) throws IOException, ParseException{ + if(request == null || request.body() == null)return null; + Request copy = request.newBuilder().build(); + Buffer buffer = new Buffer(); + copy.body().writeTo(buffer); + String requestBody = buffer.readUtf8(); + JSONObject jsonObject = (JSONObject)new JSONParser().parse(requestBody); + return jsonObject; + } } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index 376f8a660..cb646987b 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -11,6 +11,8 @@ private HttpClients() { /** * Creates builder object for construction of custom * {@link OkHttpClient} instances. + * + * @return OkHttpClient.Builder() custom builder for developer to add its own interceptors to it */ public static Builder custom() { return new OkHttpClient.Builder(); @@ -19,6 +21,9 @@ public static Builder custom() { /** * Creates {@link OkHttpClient} instance with default * configuration and provided authProvider + * + * @param auth Use IAuthenticationProvider instance provided while constructing http client + * @return OkHttpClient build with authentication provider given, default redirect and default retry handlers */ public static OkHttpClient createDefault(IAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java index 10c64a6f7..37bcd6554 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java @@ -7,6 +7,7 @@ public interface IAuthenticationProvider { * Authenticates the request * * @param request the request to authenticate + * @return Request with Authorization header added to it */ Request authenticateRequest(Request request); } diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 927ed873e..97920635d 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -40,7 +40,7 @@ public RedirectHandler(RedirectOptions redirectOptions) { } } - public boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { + boolean isRedirected(Request request, Response response, int redirectCount, RedirectOptions redirectOptions) throws IOException { // Check max count of redirects reached if(redirectCount > redirectOptions.maxRedirects()) return false; @@ -61,7 +61,7 @@ public boolean isRedirected(Request request, Response response, int redirectCoun return false; } - public Request getRedirect( + Request getRedirect( final Request request, final Response userResponse) throws ProtocolException { String location = userResponse.header("Location"); diff --git a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java b/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java deleted file mode 100644 index 917159d38..000000000 --- a/src/main/java/com/microsoft/graph/httpcore/RequestSerializer.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.microsoft.graph.httpcore; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import okhttp3.MediaType; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okio.Buffer; - -public class RequestSerializer { - - public static Map createBatchRequestsHashMap(Response batchResponse) { - if(batchResponse == null)return null; - try { - Map batchRequestsHashMap = new HashMap<>(); - JSONObject requestJSONObject = requestBodyToJSONObject(batchResponse.request()); - JSONArray requestArray = (JSONArray)requestJSONObject.get("requests"); - for(Object item : requestArray) { - JSONObject requestObject = (JSONObject)item; - - Request.Builder builder = new Request.Builder(); - - if(requestObject.get("url") != null) { - StringBuilder fullUrl = new StringBuilder(batchResponse.request().url().toString().replace("$batch","")); - fullUrl.append(requestObject.get("url").toString()); - builder.url(fullUrl.toString()); - } - if(requestObject.get("headers") != null) { - JSONObject jsonheaders = (JSONObject)requestObject.get("headers"); - for(Object key: jsonheaders.keySet()) { - String strkey = (String)key; - String strvalue = (String)jsonheaders.get(strkey); - for(String value : strvalue.split("; ")) { - builder.header(strkey, value); - } - } - } - if(requestObject.get("body") != null) { - JSONObject jsonObject = (JSONObject)requestObject.get("body"); - String bodyAsString = jsonObject.toJSONString(); - RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyAsString); - builder.method(requestObject.get("method").toString(), requestBody); - } else { - builder.method(requestObject.get("method").toString(), null); - } - batchRequestsHashMap.put(requestObject.get("id").toString(), builder.build()); - } - return batchRequestsHashMap; - - } catch (IOException | ParseException e) { e.printStackTrace(); } - return null; - } - - /* - * Convert request body to JSONObject - */ - public static JSONObject requestToJSONObject(final Request request) throws IOException, ParseException{ - Request copy = request.newBuilder().build(); - Buffer buffer = new Buffer(); - copy.body().writeTo(buffer); - String body = buffer.readUtf8(); - JSONObject json = (JSONObject)new JSONParser().parse(body); - return json; - } - - /* - * Converts String to JSONObject - */ - public static JSONObject stringToJSONObject(String input) { - JSONParser parser = new JSONParser(); - JSONObject jsonObject = null; - try { - if(input != null) { - jsonObject = (JSONObject) parser.parse(input); - } - } - catch(Exception e) { - e.printStackTrace(); - } - return jsonObject; - } - - /* - * @param list List of parameters of a single header - * @return List of headers to a String seperated by "; " - */ - public static String getHeaderValuesAsString(final List list) { - if(list == null || list.size() == 0)return ""; - StringBuilder builder = new StringBuilder(list.get(0)); - for(int i=1;i Date: Fri, 8 Mar 2019 12:14:41 +0530 Subject: [PATCH 08/10] Changed IAuthenticationProvider to ICoreAuthenticationProvider --- .../com/microsoft/graph/httpcore/AuthenticationHandler.java | 4 ++-- src/main/java/com/microsoft/graph/httpcore/HttpClients.java | 2 +- ...ticationProvider.java => ICoreAuthenticationProvider.java} | 2 +- .../microsoft/graph/httpcore/AuthenticationHandlerTest.java | 2 +- .../java/com/microsoft/graph/httpcore/HttpClientsTest.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename src/main/java/com/microsoft/graph/httpcore/{IAuthenticationProvider.java => ICoreAuthenticationProvider.java} (85%) diff --git a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java index ad1992eb6..42e9fe304 100644 --- a/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/AuthenticationHandler.java @@ -12,9 +12,9 @@ public class AuthenticationHandler implements Interceptor { public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.AUTHENTICATION; - private IAuthenticationProvider authProvider; + private ICoreAuthenticationProvider authProvider; - public AuthenticationHandler(IAuthenticationProvider authProvider) { + public AuthenticationHandler(ICoreAuthenticationProvider authProvider) { this.authProvider = authProvider; } diff --git a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java index cb646987b..4084ae91d 100644 --- a/src/main/java/com/microsoft/graph/httpcore/HttpClients.java +++ b/src/main/java/com/microsoft/graph/httpcore/HttpClients.java @@ -25,7 +25,7 @@ public static Builder custom() { * @param auth Use IAuthenticationProvider instance provided while constructing http client * @return OkHttpClient build with authentication provider given, default redirect and default retry handlers */ - public static OkHttpClient createDefault(IAuthenticationProvider auth) { + public static OkHttpClient createDefault(ICoreAuthenticationProvider auth) { return new OkHttpClient.Builder().addInterceptor(new AuthenticationHandler(auth)) .followRedirects(false) .addInterceptor(new RetryHandler()) diff --git a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java b/src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java similarity index 85% rename from src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java rename to src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java index 37bcd6554..1ca39a432 100644 --- a/src/main/java/com/microsoft/graph/httpcore/IAuthenticationProvider.java +++ b/src/main/java/com/microsoft/graph/httpcore/ICoreAuthenticationProvider.java @@ -2,7 +2,7 @@ import okhttp3.Request; -public interface IAuthenticationProvider { +public interface ICoreAuthenticationProvider { /** * Authenticates the request * diff --git a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java index e6d6eeea6..7f5feba6f 100644 --- a/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/AuthenticationHandlerTest.java @@ -14,7 +14,7 @@ public class AuthenticationHandlerTest { static String token = "TEST-TOKEN"; - public static class AuthProvider implements IAuthenticationProvider{ + public static class AuthProvider implements ICoreAuthenticationProvider{ public Request authenticateRequest(Request request) { Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + token).build(); return newRequest; diff --git a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java index feee259b1..85bb76fd5 100644 --- a/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/HttpClientsTest.java @@ -11,7 +11,7 @@ public class HttpClientsTest { @Test public void testHttpClientCreation() { - IAuthenticationProvider authprovider = new IAuthenticationProvider() { + ICoreAuthenticationProvider authprovider = new ICoreAuthenticationProvider() { public Request authenticateRequest(Request request) { Request newRequest = request.newBuilder().addHeader("Authorization", "Bearer " + "TOKEN").build(); return newRequest; From fbe12a7b8e45498b4086f97f0056abec0af71660 Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 13:44:26 +0530 Subject: [PATCH 09/10] Added null check on removing id in dependsOn --- .../com/microsoft/graph/content/MSBatchRequestContent.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java index 2fd7c5c9a..5ffa80179 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestContent.java @@ -63,7 +63,9 @@ public boolean removeBatchRequestStepWithId(String requestId) { batchRequestStepsHashMap.remove(requestId); removed = true; for(Map.Entry steps : batchRequestStepsHashMap.entrySet()) { - while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + if(steps.getValue() != null && steps.getValue().getArrayOfDependsOnIds() != null) { + while(steps.getValue().getArrayOfDependsOnIds().remove(requestId)); + } } } return removed; From e731df3e262012bc492bc1b4eada30ebf3bf66ab Mon Sep 17 00:00:00 2001 From: Nakul Sabharwal Date: Fri, 8 Mar 2019 17:25:52 +0530 Subject: [PATCH 10/10] Reordered should retry parameters --- .../graph/content/MSBatchRequestStep.java | 6 +----- .../microsoft/graph/httpcore/RedirectHandler.java | 6 +++--- .../microsoft/graph/httpcore/RetryHandler.java | 15 ++++++++------- .../httpcore/middlewareoption/IShouldRetry.java | 2 +- .../httpcore/middlewareoption/RetryOptions.java | 2 +- .../graph/httpcore/RetryHandlerTest.java | 2 +- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java index 33b5fecf1..7386decf8 100644 --- a/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java +++ b/src/main/java/com/microsoft/graph/content/MSBatchRequestStep.java @@ -14,11 +14,7 @@ public MSBatchRequestStep(String requestId, Request request, List arrayO throw new IllegalArgumentException("Request Id cannot be null."); if(request == null) new IllegalArgumentException("Request cannot be null."); - if(request.url() == null) - throw new IllegalArgumentException("Request url cannot be null."); - if(request.method() == null) - throw new IllegalArgumentException("Request method cannot be null."); - + this.requestId = requestId; this.request = request; this.arrayOfDependsOnIds = arrayOfDependsOnIds; diff --git a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java index 97920635d..dbc866990 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RedirectHandler.java @@ -27,7 +27,7 @@ public class RedirectHandler implements Interceptor{ * Initialize using default redirect options, default IShouldRedirect and max redirect value */ public RedirectHandler() { - this.mRedirectOptions = new RedirectOptions(); + this(null); } /* @@ -109,8 +109,8 @@ public Response intercept(Chain chain) throws IOException { while(true) { response = chain.proceed(request); - boolean shouldRedirect = redirectOptions.shouldRedirect().shouldRedirect(response) - && isRedirected(request, response, requestsCount, redirectOptions); + boolean shouldRedirect = isRedirected(request, response, requestsCount, redirectOptions) + && redirectOptions.shouldRedirect().shouldRedirect(response); if(!shouldRedirect) break; Request followup = getRedirect(request, response); diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 01f8bb242..5d8b18fc8 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -56,10 +56,6 @@ boolean retryRequest(Response response, int executionCount, Request request, Ret if(retryOptions != null) { shouldRetryCallback = retryOptions.shouldRetry(); } - // Call should retry callback - if(shouldRetryCallback != null && !shouldRetryCallback.shouldRetry(response, executionCount, request, retryOptions.delay())) { - return false; - } boolean shouldRetry = false; // Status codes 429 503 504 @@ -67,7 +63,11 @@ boolean retryRequest(Response response, int executionCount, Request request, Ret // Only requests with payloads that are buffered/rewindable are supported. // Payloads with forward only streams will be have the responses returned // without any retry attempt. - shouldRetry = (executionCount <= retryOptions.maxRetries()) && checkStatus(statusCode) && isBuffered(response, request); + shouldRetry = + (executionCount <= retryOptions.maxRetries()) + && checkStatus(statusCode) && isBuffered(response, request) + && shouldRetryCallback != null + && shouldRetryCallback.shouldRetry(retryOptions.delay(), executionCount, request, response); if(shouldRetry) { long retryInterval = getRetryAfter(response, retryOptions.delay(), executionCount); @@ -86,8 +86,9 @@ long getRetryAfter(Response response, long delay, int executionCount) { if(retryAfterHeader != null) { retryDelay = Long.parseLong(retryAfterHeader); } else { - retryDelay = (long)Math.pow(2.0, (double)executionCount) * DELAY_MILLISECONDS; + retryDelay = (long)((Math.pow(2.0, (double)executionCount)-1)*0.5); retryDelay = executionCount < 2 ? retryDelay : retryDelay + delay + (long)Math.random(); + retryDelay *= DELAY_MILLISECONDS; } return Math.min(retryDelay, RetryOptions.MAX_DELAY); } @@ -99,7 +100,7 @@ boolean checkStatus(int statusCode) { boolean isBuffered(Response response, Request request) { String methodName = request.method(); - if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE")) + if(methodName.equalsIgnoreCase("GET") || methodName.equalsIgnoreCase("DELETE") || methodName.equalsIgnoreCase("HEAD") || methodName.equalsIgnoreCase("OPTIONS")) return true; boolean isHTTPMethodPutPatchOrPost = methodName.equalsIgnoreCase("POST") || diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java index 0eeb9b684..249a5ba3e 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/IShouldRetry.java @@ -4,5 +4,5 @@ import okhttp3.Response; public interface IShouldRetry { - boolean shouldRetry(Response response, int executionCount, Request request, long delay); + boolean shouldRetry(long delay, int executionCount, Request request,Response response); } diff --git a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java index eb183bd1e..9010122f5 100644 --- a/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java +++ b/src/main/java/com/microsoft/graph/httpcore/middlewareoption/RetryOptions.java @@ -7,7 +7,7 @@ public class RetryOptions implements IMiddlewareControl { private IShouldRetry mShouldretry; public static final IShouldRetry DEFAULT_SHOULD_RETRY = new IShouldRetry() { @Override - public boolean shouldRetry(Response response, int executionCount, Request request, long delay) { + public boolean shouldRetry(long delay, int executionCount, Request request, Response response) { return true; } }; diff --git a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java index 48d5fdf5d..1411eb94a 100644 --- a/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java +++ b/src/test/java/com/microsoft/graph/httpcore/RetryHandlerTest.java @@ -47,7 +47,7 @@ public void testRetryHandlerWithRetryOptions() { @Test public void testRetryHandlerWithCustomRetryOptions() { IShouldRetry shouldRetry = new IShouldRetry() { - public boolean shouldRetry(Response response, int executionCount, Request request, long delay){ + public boolean shouldRetry(long delay, int executionCount, Request request,Response response){ return false; } };