aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
diff options
context:
space:
mode:
authorAnonymous <no-reply@google.com>2021-07-07 14:01:06 -0700
committerJeff Davidson <jpd@google.com>2021-07-07 23:09:19 +0000
commit212e7004acfdce76c900fd97070e2e5e8476be20 (patch)
treecf5d56ccdb862fd9676c855f919408ef940bc019 /core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
parentb47af415ba74754b442c1f9f3960b29537d07e6e (diff)
downloadvolley-212e7004acfdce76c900fd97070e2e5e8476be20.tar.gz
Android.bp has been updated to account for the new source directory structure. - 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247 Refactor Volley into a multi-module project. (#418) by Jeff Davidson <jpd@google.com> - 763c86b0bc9f66a8bb499f6a8b7fd3bdc87621a8 Remove new constructors from JsonRequests which are break... by Jeff Davidson <jpd@google.com> - 8d1b1a59e7cd1b1d3c6d8686f8831cea08f80d1f Add @NonNull annotations to Volley (#413) by Kamal Faraj <kfaraj.dev@gmail.com> - 5ba41f8670413973f587e435598f9f1724fa26e9 Allow sending any JSON with JsonArrayRequest & JsonObject... by Paul Smith <paulsmithkc@gmail.com> - 784cdd755392a6080e5eb0bf94bd7bf4ea31cf17 Update SNAPSHOT version after 1.2.0 release by Jeff Davidson <jpd@google.com> - 0d6497bab417a5f78b3c8e03ea157ada0fbfbc5d Add developers stanza to Volley POM. (#400) by Jeff Davidson <jpd@google.com> - 36274bf515a699ae5a7fe3d321206d1b803226d8 API cleanup for Async Volley stack ahead of 1.2.0 release... by Jeff Davidson <jpd@google.com> - 03f0144843fcf9ebafe512647c1c588975429452 Update environment variable name for snapshot pushes. (#3... by Jeff Davidson <jpd@google.com> - 3bd1975652687d2baa1b11a7f02b135edede8523 Publish SNAPSHOT builds to OSSRH instead of OJO. (#397) by Jeff Davidson <jpd@google.com> - 0e0c3d9cfa694f8f1400a9e9abc4bc11761fdb52 Invoke RetryPolicy#retry in the blocking executor. (#393) by Jeff Davidson <jpd@google.com> - b51831a48f06ad28f627c3624e5edb41598a2bf8 Use a consistent timebase when evaluating soft/hard TTLs.... by Jeff Davidson <jpd@google.com> - cd0839113b100f163df1ebd04ce6d5b9e36e9863 Migrate from Travis CI to GitHub Actions. (#381) by Jeff Davidson <jpd@google.com> - bdc0e393199ebf9e67c4e29e665252818eed4639 Clean up cache initialization in AsyncRequestQueue. (#380) by Jeff Davidson <jpd@google.com> - 1c0ade36edde15d02844b40351ab6f80c63b71b3 Actually allow applications to provide custom executors. by Jeff Davidson <jpd@google.com> GitOrigin-RevId: 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247 Change-Id: I4b8e4098ad5c349cb83efc867273fac1d3582a34
Diffstat (limited to 'core/src/main/java/com/android/volley/toolbox/NetworkUtility.java')
-rw-r--r--core/src/main/java/com/android/volley/toolbox/NetworkUtility.java206
1 files changed, 206 insertions, 0 deletions
diff --git a/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java b/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
new file mode 100644
index 0000000..58a3bb3
--- /dev/null
+++ b/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.volley.toolbox;
+
+import android.os.SystemClock;
+import androidx.annotation.Nullable;
+import com.android.volley.AuthFailureError;
+import com.android.volley.Cache;
+import com.android.volley.ClientError;
+import com.android.volley.Header;
+import com.android.volley.NetworkError;
+import com.android.volley.NetworkResponse;
+import com.android.volley.NoConnectionError;
+import com.android.volley.Request;
+import com.android.volley.RetryPolicy;
+import com.android.volley.ServerError;
+import com.android.volley.TimeoutError;
+import com.android.volley.VolleyError;
+import com.android.volley.VolleyLog;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.util.List;
+
+/**
+ * Utility class for methods that are shared between {@link BasicNetwork} and {@link
+ * BasicAsyncNetwork}
+ */
+final class NetworkUtility {
+ private static final int SLOW_REQUEST_THRESHOLD_MS = 3000;
+
+ private NetworkUtility() {}
+
+ /** Logs requests that took over SLOW_REQUEST_THRESHOLD_MS to complete. */
+ static void logSlowRequests(
+ long requestLifetime, Request<?> request, byte[] responseContents, int statusCode) {
+ if (VolleyLog.DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) {
+ VolleyLog.d(
+ "HTTP response for request=<%s> [lifetime=%d], [size=%s], "
+ + "[rc=%d], [retryCount=%s]",
+ request,
+ requestLifetime,
+ responseContents != null ? responseContents.length : "null",
+ statusCode,
+ request.getRetryPolicy().getCurrentRetryCount());
+ }
+ }
+
+ static NetworkResponse getNotModifiedNetworkResponse(
+ Request<?> request, long requestDuration, List<Header> responseHeaders) {
+ Cache.Entry entry = request.getCacheEntry();
+ if (entry == null) {
+ return new NetworkResponse(
+ HttpURLConnection.HTTP_NOT_MODIFIED,
+ /* data= */ null,
+ /* notModified= */ true,
+ requestDuration,
+ responseHeaders);
+ }
+ // Combine cached and response headers so the response will be complete.
+ List<Header> combinedHeaders = HttpHeaderParser.combineHeaders(responseHeaders, entry);
+ return new NetworkResponse(
+ HttpURLConnection.HTTP_NOT_MODIFIED,
+ entry.data,
+ /* notModified= */ true,
+ requestDuration,
+ combinedHeaders);
+ }
+
+ /** Reads the contents of an InputStream into a byte[]. */
+ static byte[] inputStreamToBytes(InputStream in, int contentLength, ByteArrayPool pool)
+ throws IOException {
+ PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream(pool, contentLength);
+ byte[] buffer = null;
+ try {
+ buffer = pool.getBuf(1024);
+ int count;
+ while ((count = in.read(buffer)) != -1) {
+ bytes.write(buffer, 0, count);
+ }
+ return bytes.toByteArray();
+ } finally {
+ try {
+ // Close the InputStream and release the resources by "consuming the content".
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e) {
+ // This can happen if there was an exception above that left the stream in
+ // an invalid state.
+ VolleyLog.v("Error occurred when closing InputStream");
+ }
+ pool.returnBuf(buffer);
+ bytes.close();
+ }
+ }
+
+ /**
+ * Attempts to prepare the request for a retry. If there are no more attempts remaining in the
+ * request's retry policy, the provided exception is thrown.
+ *
+ * <p>Must be invoked from a background thread, as client implementations of RetryPolicy#retry
+ * may make blocking calls.
+ *
+ * @param request The request to use.
+ */
+ static void attemptRetryOnException(final Request<?> request, final RetryInfo retryInfo)
+ throws VolleyError {
+ final RetryPolicy retryPolicy = request.getRetryPolicy();
+ final int oldTimeout = request.getTimeoutMs();
+ try {
+ retryPolicy.retry(retryInfo.errorToRetry);
+ } catch (VolleyError e) {
+ request.addMarker(
+ String.format(
+ "%s-timeout-giveup [timeout=%s]", retryInfo.logPrefix, oldTimeout));
+ throw e;
+ }
+ request.addMarker(String.format("%s-retry [timeout=%s]", retryInfo.logPrefix, oldTimeout));
+ }
+
+ static class RetryInfo {
+ private final String logPrefix;
+ private final VolleyError errorToRetry;
+
+ private RetryInfo(String logPrefix, VolleyError errorToRetry) {
+ this.logPrefix = logPrefix;
+ this.errorToRetry = errorToRetry;
+ }
+ }
+
+ /**
+ * Based on the exception thrown, decides whether to attempt to retry, or to throw the error.
+ *
+ * <p>If this method returns without throwing, {@link #attemptRetryOnException} should be called
+ * with the provided {@link RetryInfo} to consult the client's retry policy.
+ */
+ static RetryInfo shouldRetryException(
+ Request<?> request,
+ IOException exception,
+ long requestStartMs,
+ @Nullable HttpResponse httpResponse,
+ @Nullable byte[] responseContents)
+ throws VolleyError {
+ if (exception instanceof SocketTimeoutException) {
+ return new RetryInfo("socket", new TimeoutError());
+ } else if (exception instanceof MalformedURLException) {
+ throw new RuntimeException("Bad URL " + request.getUrl(), exception);
+ } else {
+ int statusCode;
+ if (httpResponse != null) {
+ statusCode = httpResponse.getStatusCode();
+ } else {
+ if (request.shouldRetryConnectionErrors()) {
+ return new RetryInfo("connection", new NoConnectionError());
+ }
+ throw new NoConnectionError(exception);
+ }
+ VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
+ NetworkResponse networkResponse;
+ if (responseContents != null) {
+ List<Header> responseHeaders;
+ responseHeaders = httpResponse.getHeaders();
+ networkResponse =
+ new NetworkResponse(
+ statusCode,
+ responseContents,
+ /* notModified= */ false,
+ SystemClock.elapsedRealtime() - requestStartMs,
+ responseHeaders);
+ if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED
+ || statusCode == HttpURLConnection.HTTP_FORBIDDEN) {
+ return new RetryInfo("auth", new AuthFailureError(networkResponse));
+ }
+ if (statusCode >= 400 && statusCode <= 499) {
+ // Don't retry other client errors.
+ throw new ClientError(networkResponse);
+ }
+ if (statusCode >= 500 && statusCode <= 599) {
+ if (request.shouldRetryServerErrors()) {
+ return new RetryInfo("server", new ServerError(networkResponse));
+ }
+ }
+ // Server error and client has opted out of retries, or 3xx. No reason to retry.
+ throw new ServerError(networkResponse);
+ }
+ return new RetryInfo("network", new NetworkError());
+ }
+ }
+}