EMASCurl是阿里云EMAS团队提供的基于libcurl的iOS平台网络库框架,能够与阿里云HTTPDNS配合使用,以降低iOS开发者接入HTTPDNS的门槛。
- 当前版本:1.1.1-http2
在您的Podfile
文件中添加如下依赖:
source 'https://github.com/aliyun/aliyun-specs.git'
target 'yourAppTarget' do
use_framework!
pod 'EMASCurl', 'x.x.x'
end
在您的Terminal中进入Podfile
所在目录,执行以下命令安装依赖:
pod install --repo-update
首先,为您的NSURLSessionConfiguration
注册EMASCurl实现。
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
[EMASCurlProtocol installIntoSessionConfiguration:config];
之后,EMASCurl可以拦截此NSURLSessionConfiguration
创建的NSURLSession
发起的请求。
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"https://httpbin.org/anything"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"请求失败,错误信息: %@", error.localizedDescription);
return;
}
NSLog(@"响应: %@", response);
NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"响应体: %@", body);
}];
[dataTask resume];
本章节介绍如何使用本仓库本地构建EMASCurl xcframework
。
构建过程中需要使用git
克隆代码、使用automake
、autoconf
、libtool
、pkg-config
等构建工具、使用gem
、ruby
、xcodeproj
等工具,请您确认这些命令行工具已经安装在本机。如果尚未安装,请参考以下安装命令:
brew install automake autoconf libtool pkg-config
brew install ruby
gem install xcodeproj
本仓库以submodule
的形式管理依赖的仓库,在克隆后需要手动拉取子模块。
git submodule update --init --recursive --progress
所依赖的子模块版本信息如下:
依赖仓库 | 版本 |
---|---|
curl | curl-8_10_1 |
nghttp2 | v1.64.0 |
./build_libcurl_xcframework.sh
运行完脚本后,在out
文件夹下会生成libcurl-HTTP2.xcframework。
pod install --repo-update
./build_emascurl_xcframework.sh
运行完脚本后,在Build/http2/emascurl
文件夹下会生成EMASCurl.xcframework,本框架目前支持HTTP1、HTTP2。
本章节介绍如何将EMASCurl添加到您的应用中。
我们提供了CocoaPods引入依赖和本地手动集成两种方式,推荐工程使用CocoaPods管理依赖。
EMASCurl和其他EMAS产品的iOS SDK,都是发布到阿里云EMAS官方维护的GitHub仓库中,因此,您需要在您的Podfile
文件中包含该仓库地址。
source 'https://github.com/aliyun/aliyun-specs.git'
为您需要依赖EMASCurl的target添加如下依赖。
use_framework!
pod 'EMASCurl', 'x.x.x'
在您的Terminal中进入Podfile
所在目录,执行以下命令安装依赖。
pod install --repo-update
您需要首先按照EMASCurl构建的步骤在本地构建出EMASCurl.xcframework,然后在Xcode工程项目中(Build Phases
-> Link Binary With Libraries
)添加对于EMASCurl.xcframework的依赖。
EMASCurl会使用zlib
进行HTTP压缩与解压,因此您需要为应用的TARGETS -> Build Settings -> Linking -> Other Linker Flags添加上-lz
与-ObjC
。
如果您使用自签名证书,还需将CA证书文件路径设置到EMASCurl中,具体请参考使用EMASCurl章节中的相关内容。
目前EMASCurl有两种开启方式,第一种方式是拦截指定NSURLSessionConfiguration
创建的NSURLSession
发起的请求,第二种方式是拦截全局的sharedSession
发起的请求。
+ (void)installIntoSessionConfiguration:(nonnull NSURLSessionConfiguration *)sessionConfiguration;
首先,为您的NSURLSessionConfiguration
安装EMASCurl。
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
[EMASCurlProtocol installIntoSessionConfiguration:config];
之后,EMASCurl可以拦截此NSURLSessionConfiguration
创建的NSURLSession
发起的请求。
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"https://httpbin.org/anything"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"请求失败,错误信息: %@", error.localizedDescription);
return;
}
NSLog(@"响应: %@", response);
NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"响应体: %@", body);
}];
[dataTask resume];
+ (void)registerCurlProtocol;
首先,开启对于sharedSession
的拦截。
[EMASCurlProtocol registerCurlProtocol];
之后,EMASCurl可以拦截sharedSession
发起的请求。
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"https://httpbin.org/anything"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"请求失败,错误信息: %@", error.localizedDescription);
return;
}
NSLog(@"响应: %@", response);
NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"响应体: %@", body);
}];
[dataTask resume];
假如您想取消对于sharedSession
的拦截,可以调用以下API:
+ (void)unregisterCurlProtocol;
EMASCurl开放了便捷的DNS hook接口,便于与HTTPDNS配合使用。只需要实现以下的DNS接口:
@protocol EMASCurlProtocolDNSResolver <NSObject>
+ (nullable NSString *)resolveDomain:(nonnull NSString *)domain;
@end
例如:
@interface MyDNSResolver : NSObject <EMASCurlProtocolDNSResolver>
@end
@implementation MyDNSResolver
+ (nullable NSString *)resolveDomain:(nonnull NSString *)domain {
HttpDnsService *httpdns = [HttpDnsService sharedInstance];
HttpdnsResult* result = [httpdns resolveHostSyncNonBlocking:domain byIpType:HttpdnsQueryIPTypeBoth];
NSLog(@"httpdns resolve result: %@", result);
if (result) {
if(result.hasIpv4Address || result.hasIpv6Address) {
NSMutableArray<NSString *> *allIPs = [NSMutableArray array];
if (result.hasIpv4Address) {
[allIPs addObjectsFromArray:result.ips];
}
if (result.hasIpv6Address) {
[allIPs addObjectsFromArray:result.ipv6s];
}
NSString *combinedIPs = [allIPs componentsJoinedByString:@","];
return combinedIPs;
}
}
return nil;
}
@end
然后调用以下方法为EMASCurl设置DNS解析器:
+ (void)setDNSResolver:(nonnull Class<EMASCurlProtocolDNSResolver>)dnsResolver;
例如:
[EMASCurlProtocol setDNSResolver:[MyDNSResolver class]];
+ (void)setHTTPVersion:(HTTPVersion)version;
EMASCurl默认使用HTTP2版本,更高版本会包含低版本的能力。需要注意的是,HTTP3需要特殊的编译方式支持,且会引入更大的包体积,具体请参考完整的文档。
HTTP1: 使用HTTP1.1 HTTP2: 首先尝试使用HTTP2,如果与服务器的HTTP2协商失败,则会退回到HTTP1.1
+ (void)setSelfSignedCAFilePath:(nonnull NSString *)selfSignedCAFilePath;
如果您的服务器使用自签名证书,您需要设置CA证书文件的路径,以确保EMASCurl能够正确验证SSL/TLS连接。
例如:
NSString *caFilePath = [[NSBundle mainBundle] pathForResource:@"my_ca" ofType:@"pem"];
[EMASCurlProtocol setSelfSignedCAFilePath:caFilePath];
+ (void)setBuiltInCookieStorageEnabled:(BOOL)enabled;
EMASCurl默认开启内部Cookie存储功能,但只支持到[RFC 6265]标准。如果您选择关闭内置Cookie存储,在依赖cookie能力时,需要自行处理请求/响应中的cookie字段。
+ (void)setConnectTimeoutIntervalForRequest:(nonnull NSMutableURLRequest *)request connectTimeoutInterval:(NSTimeInterval)connectTimeoutInSeconds;
NSURLSession
未提供设置连接超时的方式,因此EMASCurl单独提供了此功能。对于请求的整体超时时间,请直接配置NSURLRequest
中的timeoutInterval
进行设置,默认是60s。
例如:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置整体超时时间为20s
request.timeoutInterval = 20;
//设置连接超时时间为10s
[EMASCurlProtocol setConnectTimeoutIntervalForRequest:request connectTimeoutInterval:10.0];
typedef void(^EMASCurlUploadProgressUpdateBlock)(NSURLRequest * _Nonnull request,
int64_t bytesSent,
int64_t totalBytesSent,
int64_t totalBytesExpectedToSend);
+ (void)setUploadProgressUpdateBlockForRequest:(nonnull NSMutableURLRequest *)request uploadProgressUpdateBlock:(nonnull EMASCurlUploadProgressUpdateBlock)uploadProgressUpdateBlock;
由于NSURLProtocol
并未提供合适的机制来提供上传进度的跟踪,EMASCurl提供了一个额外的上传进度处理方式。您可以为每个请求设置上传进度回调。
例如:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[EMASCurlProtocol setUploadProgressUpdateBlockForRequest:request uploadProgressUpdateBlock:^(NSURLRequest * _Nonnull request, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
NSLog(@"上传进度: 已发送 %lld / 总共 %lld 字节", totalBytesSent, totalBytesExpectedToSend);
}];
typedef void(^EMASCurlMetricsObserverBlock)(NSURLRequest * _Nonnull request,
double nameLookUpTimeMS,
double connectTimeMs,
double appConnectTimeMs,
double preTransferTimeMs,
double startTransferTimeMs,
double totalTimeMs);
+ (void)setMetricsObserverBlockForRequest:(nonnull NSMutableURLRequest *)request metricsObserverBlock:(nonnull EMASCurlMetricsObserverBlock)metricsObserverBlock;
网络请求性能指标回调,可以帮助您监控请求的各项耗时指标。
例如:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[EMASCurlProtocol setMetricsObserverBlockForRequest:request metricsObserverBlock:^(NSURLRequest * _Nonnull request, double nameLookUpTimeMS, double connectTimeMs, double appConnectTimeMs, double preTransferTimeMs, double startTransferTimeMs, double totalTimeMs) {
NSLog(@"性能指标:");
NSLog(@"DNS解析耗时: %.2f ms", nameLookUpTimeMS);
NSLog(@"TCP连接耗时: %.2f ms", connectTimeMs);
NSLog(@"SSL/TLS握手耗时: %.2f ms", appConnectTimeMs);
NSLog(@"传输前准备耗时: %.2f ms", preTransferTimeMs);
NSLog(@"收到第一个字节耗时: %.2f ms", startTransferTimeMs);
NSLog(@"总耗时: %.2f ms", totalTimeMs);
}];
+ (void)setDebugLogEnabled:(BOOL)debugLogEnabled;
开启后会打印出日志记录,便于调试。
例如:
[EMASCurlProtocol setDebugLogEnabled:YES];
- Apache 2.0
- 阿里云HTTPDNS官方文档中心
- 阿里云官方技术支持:提交工单
- 阿里云EMAS开发交流钉钉群:35248489