Skip to content

Commit db69e4d

Browse files
author
jordanqin
committed
update qcloud sdk to 1.5.63
1 parent 598ad41 commit db69e4d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+942
-1444
lines changed

QCloudFoundation/foundation/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ android {
77
minSdkVersion 15
88
targetSdkVersion 28
99

10-
versionCode 10562
11-
versionName "1.5.62"
10+
versionCode 10563
11+
versionName "1.5.63"
1212

1313
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
1414

QCloudFoundation/quic/src/main/java/com/tencent/qcloud/quic/CallByNative.java renamed to QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/common/DomainSwitchException.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,9 @@
2020
* SOFTWARE.
2121
*/
2222

23-
package com.tencent.qcloud.quic;
23+
package com.tencent.qcloud.core.common;
2424

25-
import java.lang.annotation.*;
25+
import java.io.IOException;
2626

27-
@Documented
28-
@Retention(RetentionPolicy.CLASS)
29-
@Target({ElementType.METHOD})
30-
public @interface CallByNative {
27+
public class DomainSwitchException extends IOException {
3128
}

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/HttpRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ QCloudSigner getQCloudSigner() throws QCloudClientException {
200200
return null;
201201
}
202202

203-
QCloudSelfSigner getQCloudSelfSigner() throws QCloudClientException {
203+
QCloudSelfSigner getQCloudSelfSigner() {
204204
return null;
205205
}
206206

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/HttpResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public static void checkResponseSuccessful(HttpResponse response) throws QCloudS
8989
if (!response.isSuccessful()) {
9090
QCloudServiceException exception = new QCloudServiceException(response.message());
9191
exception.setStatusCode(response.code());
92+
if(response.header("x-cos-request-id") != null) {
93+
exception.setRequestId(response.header("x-cos-request-id"));
94+
}
9295
throw exception;
9396
}
9497
}

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/HttpTask.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@
2828
import com.tencent.qcloud.core.auth.QCloudSelfSigner;
2929
import com.tencent.qcloud.core.auth.QCloudSigner;
3030
import com.tencent.qcloud.core.auth.ScopeLimitCredentialProvider;
31+
import com.tencent.qcloud.core.common.DomainSwitchException;
3132
import com.tencent.qcloud.core.common.QCloudAuthenticationException;
3233
import com.tencent.qcloud.core.common.QCloudClientException;
3334
import com.tencent.qcloud.core.common.QCloudDigistListener;
3435
import com.tencent.qcloud.core.common.QCloudProgressListener;
3536
import com.tencent.qcloud.core.common.QCloudServiceException;
3637
import com.tencent.qcloud.core.task.QCloudTask;
3738
import com.tencent.qcloud.core.task.TaskExecutors;
39+
import com.tencent.qcloud.core.util.DomainSwitchUtils;
3840

3941
import java.io.IOException;
42+
import java.net.MalformedURLException;
43+
import java.net.URL;
4044
import java.util.Set;
4145
import java.util.concurrent.Executor;
4246
import java.util.concurrent.atomic.AtomicInteger;
@@ -165,6 +169,13 @@ public double getAverageStreamingSpeed(long networkMillsTook) {
165169
return 0;
166170
}
167171

172+
/**
173+
* 是否是自签名
174+
*/
175+
public boolean isSelfSigner(){
176+
return httpRequest.getQCloudSelfSigner() != null;
177+
}
178+
168179
@Override
169180
public void cancel() {
170181
this.networkProxy.cancel();
@@ -251,6 +262,27 @@ protected HttpResult<T> execute() throws QCloudClientException, QCloudServiceExc
251262
} else {
252263
throw serviceException;
253264
}
265+
} catch (QCloudClientException clientException) {
266+
if (clientException.getCause() instanceof DomainSwitchException && isDomainSwitch() && (signer != null && selfSigner == null)) {
267+
String urlString = httpRequest.url.toString().replace(DomainSwitchUtils.DOMAIN_MYQCLOUD, DomainSwitchUtils.DOMAIN_TENCENTCOS);
268+
httpRequest.setUrl(urlString);
269+
try {
270+
URL url = new URL(urlString);
271+
httpRequest.addOrReplaceHeader(HttpConstants.Header.HOST, url.getHost());
272+
} catch (MalformedURLException ignored) {
273+
}
274+
//重签名
275+
metrics.onSignRequestStart();
276+
signRequest(signer, (QCloudHttpRequest) httpRequest);
277+
metrics.onSignRequestEnd();
278+
// 重试
279+
metrics.onHttpTaskStart();
280+
httpResult = networkProxy.executeHttpRequest(httpRequest);
281+
metrics.onHttpTaskEnd();
282+
return httpResult;
283+
} else {
284+
throw clientException;
285+
}
254286
} finally {
255287
if (httpRequest.getRequestBody() instanceof ReactiveBody){
256288
try {

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/OkHttpClientImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package com.tencent.qcloud.core.http;
2424

2525
import com.tencent.qcloud.core.BuildConfig;
26+
import com.tencent.qcloud.core.http.interceptor.RedirectInterceptor;
2627
import com.tencent.qcloud.core.http.interceptor.RetryInterceptor;
2728
import com.tencent.qcloud.core.http.interceptor.TrafficControlInterceptor;
2829

@@ -56,8 +57,9 @@ public void init(QCloudHttpClient.Builder b, HostnameVerifier hostnameVerifier,
5657
logInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
5758
}
5859
OkHttpClient.Builder builder = b.mBuilder;
60+
RedirectInterceptor redirectInterceptor = new RedirectInterceptor();
5961
okHttpClient = builder
60-
.followRedirects(true)
62+
.followRedirects(false)
6163
.followSslRedirects(true)
6264
.hostnameVerifier(hostnameVerifier)
6365
.dns(dns)
@@ -69,11 +71,9 @@ public void init(QCloudHttpClient.Builder b, HostnameVerifier hostnameVerifier,
6971
.addInterceptor(logInterceptor)
7072
.addInterceptor(new RetryInterceptor(b.retryStrategy))
7173
.addInterceptor(new TrafficControlInterceptor())
74+
.addInterceptor(redirectInterceptor)
7275
.build();
73-
74-
// Dispatcher dispatcher = okHttpClient.dispatcher();
75-
// dispatcher.setMaxRequests(64); // 设置最大并发请求数
76-
// dispatcher.setMaxRequestsPerHost(36); // 设置每个主机的最大并发请求数
76+
redirectInterceptor.setClient(okHttpClient);
7777
}
7878

7979
@Override

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/QCloudHttpRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ QCloudSigner getQCloudSigner() throws QCloudClientException {
7979
}
8080

8181
@Override
82-
QCloudSelfSigner getQCloudSelfSigner() throws QCloudClientException {
82+
QCloudSelfSigner getQCloudSelfSigner() {
8383
return selfSigner;
8484
}
8585

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package com.tencent.qcloud.core.http.interceptor;
2+
3+
import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
4+
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
5+
import static java.net.HttpURLConnection.HTTP_MULT_CHOICE;
6+
import static java.net.HttpURLConnection.HTTP_SEE_OTHER;
7+
8+
import android.text.TextUtils;
9+
10+
import com.tencent.qcloud.core.common.DomainSwitchException;
11+
import com.tencent.qcloud.core.http.HttpTask;
12+
import com.tencent.qcloud.core.task.TaskManager;
13+
import com.tencent.qcloud.core.util.DomainSwitchUtils;
14+
import com.tencent.qcloud.core.util.OkhttpInternalUtils;
15+
16+
import java.io.IOException;
17+
import java.net.ProtocolException;
18+
19+
import okhttp3.HttpUrl;
20+
import okhttp3.Interceptor;
21+
import okhttp3.OkHttpClient;
22+
import okhttp3.Request;
23+
import okhttp3.RequestBody;
24+
import okhttp3.Response;
25+
26+
/**
27+
* <p>
28+
* Created by jordanqin on 2023/12/11 19:57.
29+
* Copyright 2010-2020 Tencent Cloud. All Rights Reserved.
30+
*/
31+
public class RedirectInterceptor implements Interceptor {
32+
private static final int MAX_FOLLOW_UPS = 20;
33+
private OkHttpClient client;
34+
35+
public void setClient(OkHttpClient client) {
36+
this.client = client;
37+
}
38+
39+
@Override
40+
public Response intercept(Chain chain) throws IOException {
41+
Request request = chain.request();
42+
HttpTask task = (HttpTask) TaskManager.getInstance().get((String) request.tag());
43+
44+
int followUpCount = 0;
45+
Response priorResponse = null;
46+
while (true) {
47+
if (task == null || task.isCanceled()) {
48+
throw new IOException("CANCELED");
49+
}
50+
51+
Response response = chain.proceed(request);
52+
53+
// Attach the prior response if it exists. Such responses never have a body.
54+
if (priorResponse != null) {
55+
response = response.newBuilder()
56+
.priorResponse(priorResponse.newBuilder()
57+
.body(null)
58+
.build())
59+
.build();
60+
}
61+
62+
Request followUp= followUpRequest(response, task.isDomainSwitch(), task.isSelfSigner());
63+
if (followUp == null) {
64+
return response;
65+
}
66+
67+
OkhttpInternalUtils.closeQuietly(response.body());
68+
69+
if (++followUpCount > MAX_FOLLOW_UPS) {
70+
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
71+
}
72+
request = followUp;
73+
priorResponse = response;
74+
}
75+
}
76+
77+
private Request followUpRequest(Response userResponse, boolean isDomainSwitch, boolean isSelfSigner) throws DomainSwitchException {
78+
if (userResponse == null) throw new IllegalStateException();
79+
int responseCode = userResponse.code();
80+
81+
final String method = userResponse.request().method();
82+
switch (responseCode) {
83+
case OkhttpInternalUtils.HTTP_PERM_REDIRECT:
84+
case OkhttpInternalUtils.HTTP_TEMP_REDIRECT:
85+
// "If the 307 or 308 status code is received in response to a request other than GET
86+
// or HEAD, the user agent MUST NOT automatically redirect the request"
87+
if (!method.equals("GET") && !method.equals("HEAD")) {
88+
return null;
89+
}
90+
// fall-through
91+
case HTTP_MULT_CHOICE:
92+
case HTTP_MOVED_PERM:
93+
case HTTP_MOVED_TEMP:
94+
case HTTP_SEE_OTHER:
95+
// 判断是否抛异常
96+
if(isDomainSwitch && !isSelfSigner && DomainSwitchUtils.isMyqcloudUrl(userResponse.request().url().host())
97+
&& TextUtils.isEmpty(userResponse.header("x-cos-request-id"))){
98+
throw new DomainSwitchException();
99+
}
100+
101+
String location = userResponse.header("Location");
102+
if (location == null) return null;
103+
HttpUrl url = userResponse.request().url().resolve(location);
104+
105+
// Don't follow redirects to unsupported protocols.
106+
if (url == null) return null;
107+
108+
// If configured, don't follow redirects between SSL and non-SSL.
109+
boolean sameScheme = url.scheme().equals(userResponse.request().url().scheme());
110+
if (!sameScheme && !client.followSslRedirects()) return null;
111+
112+
// Most redirects don't include a request body.
113+
Request.Builder requestBuilder = userResponse.request().newBuilder();
114+
if (OkhttpInternalUtils.permitsRequestBody(method)) {
115+
final boolean maintainBody = OkhttpInternalUtils.redirectsWithBody(method);
116+
if (OkhttpInternalUtils.redirectsToGet(method)) {
117+
requestBuilder.method("GET", null);
118+
} else {
119+
RequestBody requestBody = maintainBody ? userResponse.request().body() : null;
120+
requestBuilder.method(method, requestBody);
121+
}
122+
if (!maintainBody) {
123+
requestBuilder.removeHeader("Transfer-Encoding");
124+
requestBuilder.removeHeader("Content-Length");
125+
requestBuilder.removeHeader("Content-Type");
126+
}
127+
}
128+
129+
// When redirecting across hosts, drop all authentication headers. This
130+
// is potentially annoying to the application layer since they have no
131+
// way to retain them.
132+
if (!sameConnection(userResponse, url)) {
133+
requestBuilder.removeHeader("Authorization");
134+
}
135+
// 删掉已有的host header否则修改url后不会用新的url的host
136+
requestBuilder.removeHeader("Host");
137+
138+
return requestBuilder.url(url).build();
139+
default:
140+
return null;
141+
}
142+
}
143+
144+
private boolean sameConnection(Response response, HttpUrl followUp) {
145+
HttpUrl url = response.request().url();
146+
return url.host().equals(followUp.host())
147+
&& url.port() == followUp.port()
148+
&& url.scheme().equals(followUp.scheme());
149+
}
150+
}

QCloudFoundation/foundation/src/main/java/com/tencent/qcloud/core/http/interceptor/RetryInterceptor.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import static com.tencent.qcloud.core.http.HttpConstants.Header.RANGE;
2727
import static com.tencent.qcloud.core.http.QCloudHttpClient.HTTP_LOG_TAG;
2828

29+
import android.text.TextUtils;
30+
2931
import androidx.annotation.Nullable;
3032

33+
import com.tencent.qcloud.core.common.DomainSwitchException;
3134
import com.tencent.qcloud.core.common.QCloudServiceException;
3235
import com.tencent.qcloud.core.http.HttpConfiguration;
3336
import com.tencent.qcloud.core.http.HttpConstants;
@@ -37,6 +40,7 @@
3740
import com.tencent.qcloud.core.logger.QCloudLogger;
3841
import com.tencent.qcloud.core.task.RetryStrategy;
3942
import com.tencent.qcloud.core.task.TaskManager;
43+
import com.tencent.qcloud.core.util.DomainSwitchUtils;
4044

4145
import java.io.IOException;
4246
import java.io.InterruptedIOException;
@@ -68,7 +72,6 @@
6872
import okio.BufferedSource;
6973

7074
public class RetryInterceptor implements Interceptor {
71-
7275
private RetryStrategy retryStrategy;
7376
private RetryStrategy.WeightAndReliableAddition additionComputer = new RetryStrategy.WeightAndReliableAddition();
7477

@@ -146,6 +149,24 @@ Response processRequest(Chain chain, Request request, @Nullable HttpTask task) t
146149
throw new IOException("CANCELED");
147150
}
148151

152+
if(task.isDomainSwitch() && !task.isSelfSigner() && DomainSwitchUtils.isMyqcloudUrl(request.url().host())){
153+
try {
154+
response = executeTaskOnce(chain, request, task);
155+
// 判断响应 状态码非2XX,且没有x-cos-request-id头部
156+
if (!response.isSuccessful() && TextUtils.isEmpty(response.header("x-cos-request-id"))) {
157+
throw new DomainSwitchException();
158+
}
159+
} catch (Exception exception){
160+
// 下载convertResponse可能会产生服务端异常,这时候不用切
161+
if(exception.getCause() instanceof QCloudServiceException &&
162+
!TextUtils.isEmpty(((QCloudServiceException) exception.getCause()).getRequestId())){
163+
} else {
164+
// 没有收到响应
165+
throw new DomainSwitchException();
166+
}
167+
}
168+
}
169+
149170
int attempts = 0;
150171
long startTime = System.nanoTime();
151172

@@ -170,15 +191,23 @@ Response processRequest(Chain chain, Request request, @Nullable HttpTask task) t
170191
attempts++;
171192
int statusCode = -1;
172193
try {
173-
//解决okhttp 3.14 以上版本报错 cannot make a new request because the previous response is still open: please call response.close()
174-
if (response != null && response.body() != null) {
175-
response.close();
194+
if(attempts == 1 && response != null){
195+
// 第一次执行 且response已经有值了,说明尝试成功,则不再重复执行
196+
} else {
197+
//解决okhttp 3.14 以上版本报错 cannot make a new request because the previous response is still open: please call response.close()
198+
if (response != null && response.body() != null) {
199+
response.close();
200+
}
201+
response = executeTaskOnce(chain, request, task);
176202
}
177-
response = executeTaskOnce(chain, request, task);
178203
statusCode = response.code();
179204
e = null;
180205
} catch (IOException exception) {
181-
e = exception;
206+
if(exception instanceof DomainSwitchException){
207+
throw exception;
208+
} else {
209+
e = exception;
210+
}
182211
} catch (IllegalStateException exception){
183212
// 再次处理 okhttp 3.14 以上版本报错 cannot make a new request because the previous response is still open: please call response.close()
184213
if(exception.getMessage().startsWith("cannot make a new request because the previous response is still open: please call response.close()")){

0 commit comments

Comments
 (0)