jimu-decompiled/sources/okhttp3/internal/http/RetryAndFollowUpInterceptor.java
2025-05-13 19:24:51 +02:00

257 lines
11 KiB
Java

package okhttp3.internal.http;
import com.ubt.jimu.diy.model.DiyPreviewStep;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.HttpRetryException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.SocketTimeoutException;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.Address;
import okhttp3.Call;
import okhttp3.CertificatePinner;
import okhttp3.EventListener;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
import okhttp3.internal.Util;
import okhttp3.internal.connection.RouteException;
import okhttp3.internal.connection.StreamAllocation;
import okhttp3.internal.http2.ConnectionShutdownException;
/* loaded from: classes2.dex */
public final class RetryAndFollowUpInterceptor implements Interceptor {
private static final int MAX_FOLLOW_UPS = 20;
private Object callStackTrace;
private volatile boolean canceled;
private final OkHttpClient client;
private final boolean forWebSocket;
private volatile StreamAllocation streamAllocation;
public RetryAndFollowUpInterceptor(OkHttpClient okHttpClient, boolean z) {
this.client = okHttpClient;
this.forWebSocket = z;
}
private Address createAddress(HttpUrl httpUrl) {
SSLSocketFactory sSLSocketFactory;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
if (httpUrl.isHttps()) {
SSLSocketFactory sslSocketFactory = this.client.sslSocketFactory();
hostnameVerifier = this.client.hostnameVerifier();
sSLSocketFactory = sslSocketFactory;
certificatePinner = this.client.certificatePinner();
} else {
sSLSocketFactory = null;
hostnameVerifier = null;
certificatePinner = null;
}
return new Address(httpUrl.host(), httpUrl.port(), this.client.dns(), this.client.socketFactory(), sSLSocketFactory, hostnameVerifier, certificatePinner, this.client.proxyAuthenticator(), this.client.proxy(), this.client.protocols(), this.client.connectionSpecs(), this.client.proxySelector());
}
private Request followUpRequest(Response response, Route route) throws IOException {
String header;
HttpUrl resolve;
if (response == null) {
throw new IllegalStateException();
}
int code = response.code();
String method = response.request().method();
if (code == 307 || code == 308) {
if (!method.equals("GET") && !method.equals("HEAD")) {
return null;
}
} else {
if (code == 401) {
return this.client.authenticator().authenticate(route, response);
}
if (code == 503) {
if ((response.priorResponse() == null || response.priorResponse().code() != 503) && retryAfter(response, Integer.MAX_VALUE) == 0) {
return response.request();
}
return null;
}
if (code == 407) {
if ((route != null ? route.proxy() : this.client.proxy()).type() == Proxy.Type.HTTP) {
return this.client.proxyAuthenticator().authenticate(route, response);
}
throw new ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy");
}
if (code == 408) {
if (!this.client.retryOnConnectionFailure() || (response.request().body() instanceof UnrepeatableRequestBody)) {
return null;
}
if ((response.priorResponse() == null || response.priorResponse().code() != 408) && retryAfter(response, 0) <= 0) {
return response.request();
}
return null;
}
switch (code) {
case 300:
case DiyPreviewStep.TYPE_PROGRAM /* 301 */:
case 302:
case 303:
break;
default:
return null;
}
}
if (!this.client.followRedirects() || (header = response.header("Location")) == null || (resolve = response.request().url().resolve(header)) == null) {
return null;
}
if (!resolve.scheme().equals(response.request().url().scheme()) && !this.client.followSslRedirects()) {
return null;
}
Request.Builder newBuilder = response.request().newBuilder();
if (HttpMethod.permitsRequestBody(method)) {
boolean redirectsWithBody = HttpMethod.redirectsWithBody(method);
if (HttpMethod.redirectsToGet(method)) {
newBuilder.method("GET", null);
} else {
newBuilder.method(method, redirectsWithBody ? response.request().body() : null);
}
if (!redirectsWithBody) {
newBuilder.removeHeader("Transfer-Encoding");
newBuilder.removeHeader("Content-Length");
newBuilder.removeHeader("Content-Type");
}
}
if (!sameConnection(response, resolve)) {
newBuilder.removeHeader("Authorization");
}
return newBuilder.url(resolve).build();
}
private boolean isRecoverable(IOException iOException, boolean z) {
if (iOException instanceof ProtocolException) {
return false;
}
return iOException instanceof InterruptedIOException ? (iOException instanceof SocketTimeoutException) && !z : (((iOException instanceof SSLHandshakeException) && (iOException.getCause() instanceof CertificateException)) || (iOException instanceof SSLPeerUnverifiedException)) ? false : true;
}
private boolean recover(IOException iOException, StreamAllocation streamAllocation, boolean z, Request request) {
streamAllocation.streamFailed(iOException);
if (this.client.retryOnConnectionFailure()) {
return !(z && (request.body() instanceof UnrepeatableRequestBody)) && isRecoverable(iOException, z) && streamAllocation.hasMoreRoutes();
}
return false;
}
private int retryAfter(Response response, int i) {
String header = response.header("Retry-After");
if (header == null) {
return i;
}
if (header.matches("\\d+")) {
return Integer.valueOf(header).intValue();
}
return Integer.MAX_VALUE;
}
private boolean sameConnection(Response response, HttpUrl httpUrl) {
HttpUrl url = response.request().url();
return url.host().equals(httpUrl.host()) && url.port() == httpUrl.port() && url.scheme().equals(httpUrl.scheme());
}
public void cancel() {
this.canceled = true;
StreamAllocation streamAllocation = this.streamAllocation;
if (streamAllocation != null) {
streamAllocation.cancel();
}
}
@Override // okhttp3.Interceptor
public Response intercept(Interceptor.Chain chain) throws IOException {
Response proceed;
Request followUpRequest;
Request request = chain.request();
RealInterceptorChain realInterceptorChain = (RealInterceptorChain) chain;
Call call = realInterceptorChain.call();
EventListener eventListener = realInterceptorChain.eventListener();
StreamAllocation streamAllocation = new StreamAllocation(this.client.connectionPool(), createAddress(request.url()), call, eventListener, this.callStackTrace);
this.streamAllocation = streamAllocation;
Response response = null;
int i = 0;
while (!this.canceled) {
try {
try {
try {
proceed = realInterceptorChain.proceed(request, streamAllocation, null, null);
if (response != null) {
proceed = proceed.newBuilder().priorResponse(response.newBuilder().body(null).build()).build();
}
try {
followUpRequest = followUpRequest(proceed, streamAllocation.route());
} catch (IOException e) {
streamAllocation.release();
throw e;
}
} catch (RouteException e2) {
if (!recover(e2.getLastConnectException(), streamAllocation, false, request)) {
throw e2.getFirstConnectException();
}
}
} catch (IOException e3) {
if (!recover(e3, streamAllocation, !(e3 instanceof ConnectionShutdownException), request)) {
throw e3;
}
}
if (followUpRequest == null) {
if (!this.forWebSocket) {
streamAllocation.release();
}
return proceed;
}
Util.closeQuietly(proceed.body());
int i2 = i + 1;
if (i2 > 20) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + i2);
}
if (followUpRequest.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", proceed.code());
}
if (!sameConnection(proceed, followUpRequest.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(this.client.connectionPool(), createAddress(followUpRequest.url()), call, eventListener, this.callStackTrace);
this.streamAllocation = streamAllocation;
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + proceed + " didn't close its backing stream. Bad interceptor?");
}
response = proceed;
request = followUpRequest;
i = i2;
} catch (Throwable th) {
streamAllocation.streamFailed(null);
streamAllocation.release();
throw th;
}
}
streamAllocation.release();
throw new IOException("Canceled");
}
public boolean isCanceled() {
return this.canceled;
}
public void setCallStackTrace(Object obj) {
this.callStackTrace = obj;
}
public StreamAllocation streamAllocation() {
return this.streamAllocation;
}
}