Skip to content

aliyun/alicloud-ios-sdk-emascurl

Repository files navigation

EMASCurl

GitHub version License

EMASCurl是阿里云EMAS团队提供的基于libcurl的iOS平台网络库框架,能够与阿里云HTTPDNS配合使用,以降低iOS开发者接入HTTPDNS的门槛。

目录

最新版本

  • 当前版本:1.1.1-http2

快速入门

从CocoaPods引入依赖

在您的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

使用EMASCurl发送网络请求

首先,为您的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

本章节介绍如何使用本仓库本地构建EMASCurl xcframework

构建工具安装

构建过程中需要使用git克隆代码、使用automakeautoconflibtoolpkg-config等构建工具、使用gemrubyxcodeproj等工具,请您确认这些命令行工具已经安装在本机。如果尚未安装,请参考以下安装命令:

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

构建libcurl.xcframework

./build_libcurl_xcframework.sh

运行完脚本后,在out文件夹下会生成libcurl-HTTP2.xcframework

构建EMASCurl xcframework

pod install --repo-update
./build_emascurl_xcframework.sh

运行完脚本后,在Build/http2/emascurl文件夹下会生成EMASCurl.xcframework,本框架目前支持HTTP1、HTTP2。

集成EMASCurl

本章节介绍如何将EMASCurl添加到您的应用中。

我们提供了CocoaPods引入依赖和本地手动集成两种方式,推荐工程使用CocoaPods管理依赖。

CocoaPods引入依赖

指定Master仓库和阿里云仓库

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

本地手动集成依赖

将framework文件添加到工程中

您需要首先按照EMASCurl构建的步骤在本地构建出EMASCurl.xcframework,然后在Xcode工程项目中(Build Phases -> Link Binary With Libraries)添加对于EMASCurl.xcframework的依赖。

添加Linker Flags

EMASCurl会使用zlib进行HTTP压缩与解压,因此您需要为应用的TARGETS -> Build Settings -> Linking -> Other Linker Flags添加上-lz-ObjC

添加CA证书文件路径(如果使用自签名证书)

如果您使用自签名证书,还需将CA证书文件路径设置到EMASCurl中,具体请参考使用EMASCurl章节中的相关内容。

使用EMASCurl

开启EMASCurl拦截

目前EMASCurl有两种开启方式,第一种方式是拦截指定NSURLSessionConfiguration创建的NSURLSession发起的请求,第二种方式是拦截全局的sharedSession发起的请求。

拦截NSURLSessionConfiguration

+ (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];

拦截sharedSession

+ (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;

与HTTPDNS配合使用

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]];

选择HTTP版本

+ (void)setHTTPVersion:(HTTPVersion)version;

EMASCurl默认使用HTTP2版本,更高版本会包含低版本的能力。需要注意的是,HTTP3需要特殊的编译方式支持,且会引入更大的包体积,具体请参考完整的文档。

HTTP1: 使用HTTP1.1 HTTP2: 首先尝试使用HTTP2,如果与服务器的HTTP2协商失败,则会退回到HTTP1.1

设置CA证书文件路径

+ (void)setSelfSignedCAFilePath:(nonnull NSString *)selfSignedCAFilePath;

如果您的服务器使用自签名证书,您需要设置CA证书文件的路径,以确保EMASCurl能够正确验证SSL/TLS连接。

例如:

NSString *caFilePath = [[NSBundle mainBundle] pathForResource:@"my_ca" ofType:@"pem"];
[EMASCurlProtocol setSelfSignedCAFilePath:caFilePath];

设置Cookie存储

+ (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];

License

  • Apache 2.0

联系我们

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •