tencent cloud

Custom Network Layer
Last updated:2026-02-05 11:13:40
Custom Network Layer
Last updated: 2026-02-05 11:13:40

Introduction

This article describes how to customize the network layer in the COS SDK.

Feature Overview

By default, the network layer of COS SDK is implemented based on OKHTTP and also provides a network implementation for the QUIC protocol via QUIC SDK. Now, COS SDK also supports a more flexible custom network layer, allowing developers to take over and control the network communication part in COS SDK.
Therefore, if the default network implementation of COS SDK does not meet your requirements, or if your APP has already developed a robust custom network library, you can use the approach provided in this document to customize the network layer in COS SDK.
In the custom network layer, DNS resolution optimization, network path acceleration, poor network condition optimization, and other network optimizations can be performed more flexibly.
Note:
The custom network layer feature requires a certain understanding of network programming. If you are not sure how to use this feature, we recommend using the default network implementation of COS SDK.

Scheme Overview

Android

1. Inherit NetworkClient to implement a custom network Client for managing and configuring network requests, and so on.
2. Inherit NetworkProxy to implement a network request proxy for executing specific network requests.
3. Configure the COS SDK via the setCustomizeNetworkClient method of CosXmlServiceConfig.

iOS

1. Inherit QCloudCustomLoaderTask to implement the network request task class.
2. Inherit QCloudCustomSession to implement a custom network Session for building custom tasks, progress callbacks, completion callbacks, and other logic handling.
3. Implement the QCloudCustomLoader proxy to enable custom networks and build custom Session instances.

Implementation Sample

Note:
The following examples are provided as basic illustrative examples only. The actual implementation should be refined or modified according to your business requirements.

Android

Android uses OKHTTP and the built-in HttpURLConnection as examples.
OKHTTP
HttpURLConnection
1. Inherit NetworkClient to implement a custom network Client.
import com.tencent.qcloud.core.http.HttpLogger;
import com.tencent.qcloud.core.http.HttpLoggingInterceptor;
import com.tencent.qcloud.core.http.NetworkClient;
import com.tencent.qcloud.core.http.NetworkProxy;
import com.tencent.qcloud.core.http.QCloudHttpClient;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import okhttp3.Dns;
import okhttp3.OkHttpClient;

/**
* Implement a custom network Client here, for example, an OkHttpClient instance.
*/
public class CustomizeOkHttpNetworkClient extends NetworkClient {
private static final String TAG = "CustomizeOkHttpNetworkClient";

private OkHttpClient okHttpClient;

@Override
public void init(QCloudHttpClient.Builder b, HostnameVerifier hostnameVerifier,
final Dns dns, HttpLogger httpLogger) {
super.init(b, hostnameVerifier, dns, httpLogger);
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(httpLogger);
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15 * 1000, TimeUnit.MILLISECONDS)
.readTimeout(30 * 1000, TimeUnit.MILLISECONDS)
.writeTimeout(30 * 1000, TimeUnit.MILLISECONDS)
.addInterceptor(logInterceptor);
okHttpClient = builder.build();
}

@Override
public NetworkProxy getNetworkProxy() {
CustomizeOkHttpNetworkProxy customizeOkHttpNetworkProxy = new CustomizeOkHttpNetworkProxy(okHttpClient);
return customizeOkHttpNetworkProxy;
}
}
Note:
For more complete examples, please visit GitHub to view them.
2. Inherit NetworkProxy to implement a network request proxy.
import com.tencent.qcloud.core.http.NetworkProxy;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
* Implement a network request here, for example, okhttp's Call.
*/
public class CustomizeOkHttpNetworkProxy<T> extends NetworkProxy<T> {
private static final String TAG = "CustomizeOkHttpNetworkProxy";
private Call httpCall;
private OkHttpClient okHttpClient;

public CustomizeOkHttpNetworkProxy(OkHttpClient okHttpClient){
this.okHttpClient = okHttpClient;
}

@Override
public void cancel(){
if (httpCall != null) {
httpCall.cancel();
}
}

@Override
public Response callHttpRequest(Request okHttpRequest) throws IOException {
httpCall = okHttpClient.newCall(okHttpRequest);
return httpCall.execute();
}
}
Note:
For more complete examples, please visit GitHub to view them.
3. Configure the COS SDK.
CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder(
.setRegion(region))
// Other configurations remain unchanged.
.setCustomizeNetworkClient(new CustomizeOkHttpNetworkClient()) // Set the custom network client mentioned above
.builder();
1. Inherit NetworkClient to implement a custom network Client.
import android.util.Log;
import com.tencent.qcloud.core.http.HttpLogger;
import com.tencent.qcloud.core.http.NetworkClient;
import com.tencent.qcloud.core.http.NetworkProxy;
import com.tencent.qcloud.core.http.QCloudHttpClient;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HostnameVerifier;
import okhttp3.Dns;
import okhttp3.Request;
import okio.BufferedSink;
import okio.Okio;

/**
* Implement a custom network Client here.
*/
public class CustomizeNetworkClient extends NetworkClient {
private static final String TAG = "CustomizeNetworkClient";

private HttpURLConnectionManager httpURLConnectionManager;
@Override
public void init(QCloudHttpClient.Builder b, HostnameVerifier hostnameVerifier, Dns dns, HttpLogger httpLogger) {
super.init(b, hostnameVerifier, dns, httpLogger);
httpURLConnectionManager = new HttpURLConnectionManager();
}

@Override
public NetworkProxy getNetworkProxy() {
return new CustomizeNetworkProxy(httpURLConnectionManager);
}

public static class HttpURLConnectionManager {
private static final int CONNECT_TIMEOUT = 5000;
private static final int READ_TIMEOUT = 5000;

public HttpURLConnection createConnection(Request request) throws IOException {
Log.d("NetworkRequest", "Request URL: " + request.url());
Log.d("NetworkRequest", "Request method: " + request.method());

URL url = new URL(request.url().toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);

connection.setRequestMethod(request.method());

// Set headers
for (String name : request.headers().names()) {
connection.setRequestProperty(name, request.header(name));
Log.d("NetworkRequest", "Header: " + name + " = " + request.header(name));
}

// Set body
if (request.body() != null) {
connection.setDoOutput(true);
try (OutputStream outputStream = connection.getOutputStream();
BufferedSink bufferedSink = Okio.buffer(Okio.sink(outputStream))) {
request.body().writeTo(bufferedSink);
}
Log.d("NetworkRequest", "Request body set");
}

return connection;
}
}
}
Note:
For more complete examples, please visit GitHub to view them.
2. Inherit NetworkProxy to implement a network request proxy.
import android.text.TextUtils;
import android.util.Log;
import com.tencent.qcloud.core.http.NetworkProxy;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSource;
import okio.Okio;

/**
* Implement a network request here.
*/
public class CustomizeNetworkProxy<T> extends NetworkProxy<T> {
private static final String TAG = "CustomizeNetworkProxy";
private HttpURLConnection connection;
private CustomizeNetworkClient.HttpURLConnectionManager httpURLConnectionManager;

public CustomizeNetworkProxy(CustomizeNetworkClient.HttpURLConnectionManager httpURLConnectionManager) {
this.httpURLConnectionManager = httpURLConnectionManager;
}

@Override
protected void cancel() {
if (connection != null) {
connection.disconnect();
}
}

@Override
public Response callHttpRequest(Request okHttpRequest) throws IOException {
try {
connection = httpURLConnectionManager.createConnection(okHttpRequest);
int responseCode = connection.getResponseCode();
Log.d("NetworkRequest", "Response code: " + responseCode);
Response response = convertToOkHttpResponse(connection);
Log.d("NetworkRequest", "Response headers: " + response.headers());
return response;
} catch (IOException e) {
Log.e("NetworkRequest", "Failed to execute HTTP request", e);
throw e;
}
}

@Override
protected void disconnect(){
if (connection != null) {
connection.disconnect();
}
}

private Response convertToOkHttpResponse(HttpURLConnection connection) throws IOException {
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
String contentType = connection.getContentType();
int contentLength = connection.getContentLength();

// Convert headers
Headers.Builder headersBuilder = new Headers.Builder();
Map<String, List<String>> headerFields = connection.getHeaderFields();
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
String name = entry.getKey();
if (TextUtils.isEmpty(name)) continue;
for (String value : entry.getValue()) {
headersBuilder.add(name, value);
}
}
Headers headers = headersBuilder.build();

// Convert body
BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
ResponseBody body = new ResponseBody() {
@Override
public MediaType contentType() {
if(TextUtils.isEmpty(contentType)){
return null;
} else {
return MediaType.parse(contentType);
}
}

@Override
public long contentLength() {
return contentLength;
}

@Override
public BufferedSource source() {
return source;
}
};

// Build OkHttp Response
Request request = new Request.Builder()
.url(connection.getURL().toString())
.build();

return new Response.Builder()
.request(request)
.protocol(Protocol.HTTP_1_1)
.code(code)
.message(message)
.headers(headers)
.body(body)
.build();
}
}
Note:
For more complete examples, please visit GitHub to view them.
3. Configure the COS SDK.
CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder(
.setRegion(region))
// Other configurations remain unchanged.
.setCustomizeNetworkClient(new CustomizeNetworkClient()) // Set the above-mentioned custom network client
.builder();

iOS

iOS uses AFNetworking as an example.
1. Inherit QCloudCustomLoaderTask to implement the custom task class QCloudAFLoaderTask.
#import <Foundation/Foundation.h>
#import "QCloudCustomLoader.h"

@interface QCloudAFLoaderTask : QCloudCustomLoaderTask

@end
Note:
For more complete examples, please visit GitHub.
#import "QCloudAFLoaderTask.h"
#import "QCloudAFLoaderSession.h"
#import "AFNetworking/AFNetworking.h"
@interface QCloudAFLoaderTask ()

@property (nonatomic,strong)QCloudCustomSession *customSession;
@property (nonatomic,strong)NSMutableURLRequest *httpRequest;
@property (nonatomic,strong)NSURL *fromFile;
@property (nonatomic,strong)NSURLSessionDataTask *task;

@end

@implementation QCloudAFLoaderTask

// Custom task constructor
- (instancetype)initWithHTTPRequest:(NSMutableURLRequest *)httpRequest
fromFile:(NSURL *)fromFile
session:(QCloudCustomSession *)session{
self = [super init];
if (self) {
self.fromFile = fromFile;
self.httpRequest = httpRequest;
self.currentRequest = httpRequest;
self.originalRequest = httpRequest;
self.customSession = session;
}
return self;
}
// Custom task startup method. This method is implemented by the business layer and called by the SDK.
// Use your own network library to construct and initiate network requests.
// The logic for progress callbacks, completion callbacks, etc., calls the corresponding methods of the custom session and passes them to the sdk.
-(void)resume{
QCloudWeakSelf(self);
if (!self.fromFile) {
self.task = [[[QCloudAFLoaderSession session] manager] dataTaskWithRequest:self.httpRequest uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
QCloudStrongSelf(self);
// Handling upload progress callbacks.
[strongself.customSession customTask:self didSendBodyData:uploadProgress.completedUnitCount totalBytesSent:uploadProgress.totalUnitCount totalBytesExpectedToSend:uploadProgress.totalUnitCount];
} downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
QCloudStrongSelf(self);
// Handling download progress callbacks.
[strongself.customSession customTask:self didSendBodyData:downloadProgress.completedUnitCount totalBytesSent:downloadProgress.totalUnitCount totalBytesExpectedToSend:downloadProgress.totalUnitCount];
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
QCloudStrongSelf(self);
// Handling completion progress callbacks.
[strongself.customSession customTask:strongself didReceiveResponse:response completionHandler:nil];
[strongself.customSession customTask:strongself didReceiveData:responseObject];
[strongself.customSession customTask:strongself didCompleteWithError:error];
}];
// Initiate a request
[self.task resume];
}else{
// Upload local file
self.task = [[[QCloudAFLoaderSession session] manager] uploadTaskWithRequest:self.httpRequest fromFile:self.fromFile progress:^(NSProgress * _Nonnull uploadProgress) {
QCloudStrongSelf(self);
// Handling upload progress callbacks.
[strongself.customSession customTask:strongself didSendBodyData:uploadProgress.completedUnitCount totalBytesSent:uploadProgress.totalUnitCount totalBytesExpectedToSend:uploadProgress.totalUnitCount];
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
QCloudStrongSelf(self);
// Handling completion progress callbacks.
[strongself.customSession customTask:strongself didReceiveResponse:response completionHandler:nil];
[strongself.customSession customTask:strongself didReceiveData:responseObject];
[strongself.customSession customTask:strongself didCompleteWithError:error];
}];
// Initiate a request
[self.task resume];
}
}

- (void)cancel{
[self.task cancel];
}
@end
Note:
For more complete examples, please visit GitHub.
2. Inherit QCloudCustomSession to implement a custom Session class QCloudAFLoaderSession.
#import <Foundation/Foundation.h>
#import "QCloudCore/QCloudCustomLoader.h"
#import "AFNetworking/AFNetworking.h"
NS_ASSUME_NONNULL_BEGIN

@interface QCloudAFLoaderSession : QCloudCustomSession
// Custom session holds an instance of AFURLSessionManager.
@property (nonatomic,strong)AFURLSessionManager *manager;

+(QCloudAFLoaderSession *)session;

@end
Note:
For more complete examples, please visit GitHub.
#import "QCloudAFLoaderSession.h"
#import "QCloudAFLoaderTask.h"
@implementation QCloudAFLoaderSession

// QCloudAFLoaderSession is a singleton
+(QCloudAFLoaderSession *)session{
static QCloudAFLoaderSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
session = [[QCloudAFLoaderSession alloc] init];
});
return session;
}

- (instancetype)init
{
self = [super init];
if (self) {
// Initialize AFURLSessionManager;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
self.manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
self.manager.responseSerializer = [[AFCompoundResponseSerializer alloc]init];
}
return self;
}

-(QCloudCustomLoaderTask *)taskWithRequset:(NSMutableURLRequest *)request
fromFile:(NSURL *)fromFile{
QCloudAFLoaderTask * task = [[QCloudAFLoaderTask alloc]initWithHTTPRequest:request fromFile:fromFile session:[QCloudAFLoaderSession session]];
return task;
}
@end
Note:
For more complete examples, please visit GitHub.
3. Custom QCloudCustomLoader proxy implementation class implements QCloudAFLoader proxy.
#import <Foundation/Foundation.h>
#import "QCloudCustomLoader.h"
NS_ASSUME_NONNULL_BEGIN

@interface QCloudAFLoader : NSObject <QCloudCustomLoader>

@end
Note:
For more complete examples, please visit GitHub.
#import "QCloudAFLoader.h"
#import "QCloudAFLoaderSession.h"
@implementation QCloudAFLoader
// Holds a custom session instance.
-(QCloudCustomSession *)session{
return [QCloudAFLoaderSession session];
}
// Whether to enable the current network layer
-(BOOL)enable:(QCloudHTTPRequest *)httpRequest{
return YES;
}
@end

Note:
For more complete examples, please visit GitHub.
4. Configure the COS SDK to load the custom network layer into the COS SDK and enable it.
// During project launch, initialize the custom loader and call the addLoader method of [QCloudLoaderManager manager] to register it into the SDK's custom network loader.
// Supports adding multiple custom loaders for dynamic switching at the business layer.
[[QCloudLoaderManager manager]addLoader: [[QCloudAFLoader alloc]init]];
// Enable the custom network layer switch. When this switch is disabled, all custom loaders become unavailable.
[QCloudLoaderManager manager].enable = YES;


Was this page helpful?
You can also Contact Sales or Submit a Ticket for help.
Yes
No

Feedback