tencent cloud

Cloud Object Storage

Release Notes and Announcements
Release Notes
Announcements
Product Introduction
Overview
Features
Use Cases
Strengths
Concepts
Regions and Access Endpoints
Specifications and Limits
Service Regions and Service Providers
Billing
Billing Overview
Billing Method
Billable Items
Free Tier
Billing Examples
Viewing and Downloading Bill
Payment Overdue
FAQs
Getting Started
Console
Getting Started with COSBrowser
User Guide
Creating Request
Bucket
Object
Data Management
Batch Operation
Global Acceleration
Monitoring and Alarms
Operations Center
Data Processing
Content Moderation
Smart Toolbox
Data Processing Workflow
Application Integration
User Tools
Tool Overview
Installation and Configuration of Environment
COSBrowser
COSCLI (Beta)
COSCMD
COS Migration
FTP Server
Hadoop
COSDistCp
HDFS TO COS
GooseFS-Lite
Online Tools
Diagnostic Tool
Use Cases
Overview
Access Control and Permission Management
Performance Optimization
Accessing COS with AWS S3 SDK
Data Disaster Recovery and Backup
Domain Name Management Practice
Image Processing
Audio/Video Practices
Workflow
Direct Data Upload
Content Moderation
Data Security
Data Verification
Big Data Practice
COS Cost Optimization Solutions
Using COS in the Third-party Applications
Migration Guide
Migrating Local Data to COS
Migrating Data from Third-Party Cloud Storage Service to COS
Migrating Data from URL to COS
Migrating Data Within COS
Migrating Data Between HDFS and COS
Data Lake Storage
Cloud Native Datalake Storage
Metadata Accelerator
GooseFS
Data Processing
Data Processing Overview
Image Processing
Media Processing
Content Moderation
File Processing Service
File Preview
Troubleshooting
Obtaining RequestId
Slow Upload over Public Network
403 Error for COS Access
Resource Access Error
POST Object Common Exceptions
API Documentation
Introduction
Common Request Headers
Common Response Headers
Error Codes
Request Signature
Action List
Service APIs
Bucket APIs
Object APIs
Batch Operation APIs
Data Processing APIs
Job and Workflow
Content Moderation APIs
Cloud Antivirus API
SDK Documentation
SDK Overview
Preparations
Android SDK
C SDK
C++ SDK
.NET(C#) SDK
Flutter SDK
Go SDK
iOS SDK
Java SDK
JavaScript SDK
Node.js SDK
PHP SDK
Python SDK
React Native SDK
Mini Program SDK
Error Codes
Harmony SDK
Endpoint SDK Quality Optimization
Security and Compliance
Data Disaster Recovery
Data Security
Cloud Access Management
FAQs
Popular Questions
General
Billing
Domain Name Compliance Issues
Bucket Configuration
Domain Names and CDN
Object Operations
Logging and Monitoring
Permission Management
Data Processing
Data Security
Pre-signed URL Issues
SDKs
Tools
APIs
Agreements
Service Level Agreement
Privacy Policy
Data Processing And Security Agreement
Contact Us
Glossary

Custom Network Layer

PDF
Focus Mode
Font Size
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;



Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback