EMASCurl/EMASCurlProtocol.h (43 lines of code) (raw):

// // EMASCurlProtocol.h // EMASCurl // // Created by xin yu on 2024/10/29. // #ifndef EMASCurlProtocol_h #define EMASCurlProtocol_h #import <Foundation/Foundation.h> /// 提供一个便捷易用的DNS Hook机制,类似OKHTTP中的DNS配置 @protocol EMASCurlProtocolDNSResolver <NSObject> /// 实现这个方法时,解析域名得到的多个IP通过','拼接,如 10.10.10.10,11.11.11.11,12.12.12.12。 /// 如果涉及IPv4和IPv6协议,无需特别区分,直接将IPv6的IP和IPv4的IP拼接到一起返回,EMASCurl会自行决策如何请求 /// /// param @domain 请求域名 /// return 解析后的IP地址,多个IP通过','拼接,如 /// 10.10.10.10,11.11.11.11,12.12.12.12 /// 10.10.10.10,5be8:dde9:7f0b:d5a7:bd01:b3be:9c69:573b,12.12.12.12,5be8:dde9:7f0b:d5a7:bd01:b3be:9c69:573b /// 返回nil时,EMASCurl会使用默认的DNS解析 + (nullable NSString *)resolveDomain:(nonnull NSString *)domain; @end /// 由于`NSURLProtocol`并未提供合适的机制来提供上传进度的跟踪,我们提供一个额外的上传进度处理方式 /// /// param @request 发起请求使用的请求实例 /// param @bytesSent: 已发送的字节数 /// param @totalBytesSent: 已发送的总字节数 /// param @totalBytesExpectedToSend: 总字节数 typedef void(^EMASCurlUploadProgressUpdateBlock)(NSURLRequest * _Nonnull request, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend); /// 网络请求性能指标回调 /// /// param @request 发起请求使用的请求实例 /// param @nameLookUpTimeMS DNS解析耗时,单位毫秒 /// param @connectTimeMs TCP连接耗时,单位毫秒 /// param @appConnectTimeMs SSL/TLS握手耗时,单位毫秒 /// param @preTransferTimeMs 从开始到传输前准备完成的耗时,单位毫秒 /// param @startTransferTimeMs 从开始到收到第一个字节的耗时,单位毫秒 /// param @totalTimeMs 整个请求的总耗时,单位毫秒 typedef void(^EMASCurlMetricsObserverBlock)(NSURLRequest * _Nonnull request, BOOL success, NSError * _Nullable error, double nameLookUpTimeMS, double connectTimeMs, double appConnectTimeMs, double preTransferTimeMs, double startTransferTimeMs, double totalTimeMs); // HTTP版本,高版本一定包含支持低版本 typedef NS_ENUM(NSInteger, HTTPVersion) { HTTP1, HTTP2, HTTP3 }; @interface EMASCurlProtocol : NSURLProtocol // 拦截使用自定义`NSURLSessionConfiguration`创建的session发起的requst + (void)installIntoSessionConfiguration:(nonnull NSURLSessionConfiguration *)sessionConfiguration; // 拦截`sharedSession`发起的request + (void)registerCurlProtocol; // 注销对`sharedSession`的拦截 + (void)unregisterCurlProtocol; // 设置支持的HTTP版本,默认HTTP2 // 更高版本一定包含低版本 // HTTP3需要特殊的编译方式支持,且会引入更大的包体积,参考完整的readme文档 + (void)setHTTPVersion:(HTTPVersion)version; // 设置是否开启内部Gzip压缩,开启后,请求的header中会自动添加`Accept-Encoding: deflate, gzip`,并自动解压 // 默认开启 // 若关闭,则依赖gzip能力时,需要自行处理请求/响应中的gzip字段 + (void)setBuiltInGzipEnabled:(BOOL)enabled; // 设置CA证书文件路径,在使用自签名证书做测试时使用 + (void)setSelfSignedCAFilePath:(nonnull NSString *)selfSignedCAFilePath; // 是否开启内部重定向支持 + (void)setBuiltInRedirectionEnabled:(BOOL)enabled; // 设置是否开启调试日志 + (void)setDebugLogEnabled:(BOOL)debugLogEnabled; // 设置DNS解析器 + (void)setDNSResolver:(nonnull Class<EMASCurlProtocolDNSResolver>)dnsResolver; // 设置连接超时,单位秒 // `NSURLSession`未提供设置连接超时的方式,因此这里单独提供 // 对于请求的整体超时时间,请直接配置`NSURLRequest`中的`timeoutInterval`进行设置,默认是60s + (void)setConnectTimeoutIntervalForRequest:(nonnull NSMutableURLRequest *)request connectTimeoutInterval:(NSTimeInterval)connectTimeoutInSeconds; // 设置上传进度回调 + (void)setUploadProgressUpdateBlockForRequest:(nonnull NSMutableURLRequest *)request uploadProgressUpdateBlock:(nonnull EMASCurlUploadProgressUpdateBlock)uploadProgressUpdateBlock; // 设置性能指标回调 + (void)setMetricsObserverBlockForRequest:(nonnull NSMutableURLRequest *)request metricsObserverBlock:(nonnull EMASCurlMetricsObserverBlock)metricsObserverBlock; // 设置拦截域名白名单,处理请求时,先检查黑名单,再检查白名单 // 只拦截白名单中的域名 // 传入nil时,清除白名单 + (void)setHijackDomainWhiteList:(nullable NSArray<NSString *> *)domainWhiteList; // 设置拦截域名黑名单,处理请求时,先检查黑名单,再检查白名单 // 不拦截黑名单中的域名 // 传入nil时,清除黑名单 + (void)setHijackDomainBlackList:(nullable NSArray<NSString *> *)domainBlackList; // 设置用于公钥固定(Public Key Pinning)的公钥文件路径。 // libcurl 会使用此文件中的公钥信息来验证服务器证书链中的公钥。 // 传入nil时,清除公钥固定设置。 // // 要求公钥 PEM 文件的结构: // 1. 公钥 PEM 文件必须包含一个有效的公钥信息,格式为 PEM 格式, // 即包含 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 区块,内容为公钥的 base64 编码。 // 2. 文件内容示例: // -----BEGIN PUBLIC KEY----- // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A... // ...base64 data... // -----END PUBLIC KEY----- // // 如果用户仅持有 PEM 格式的证书文件,而不是单独的公钥 PEM 文件,可以通过以下命令从证书中提取公钥: // // 使用 OpenSSL 工具: // ```bash // openssl x509 -in your-cert.pem -pubkey -noout -out publickey.pem // ``` // 该命令会从 PEM 证书文件(`your-cert.pem`)中提取公钥,并将公钥保存到 `publickey.pem` 文件中。 // 生成的公钥文件应符合上述结构要求,可以直接用于公钥固定。 + (void)setPublicKeyPinningKeyPath:(nullable NSString *)publicKeyPath; // 设置手动代理服务器。设置后会覆盖系统代理设置。 // 传入nil时,恢复使用系统代理设置。 // 代理字符串格式:[protocol://]user:password@host[:port] // 例如: http://user:pass@myproxy.com:8080 或 socks5://127.0.0.1:1080 + (void)setManualProxyServer:(nullable NSString *)proxyServerURL; @end #endif /* EMASCurlProtocol_h */