WEEX + HTTPDNS iOS解决方案

简介: ## WEEX + HTTPDNS iOS解决方案 由于`WebView`并未暴露处设置DNS的接口,因而在`WebView`场景下使用`HttpDns`存在很多无法限制,但如果接入`WEEX`,则可以较好地植入`HTTPDNS`,本文主要介绍在`WEEX`场景下接入`HTTPDNS`的方案细节。 在`WEEX`运行时环境下,所有的逻辑最终都会转换到`Native Runtime`中执

WEEX + HTTPDNS iOS解决方案

由于WebView并未暴露处设置DNS的接口,因而在WebView场景下使用HttpDns存在很多无法限制,但如果接入WEEX,则可以较好地植入HTTPDNS,本文主要介绍在WEEX场景下接入HTTPDNS的方案细节。

在WEEX运行时环境下,所有的逻辑最终都会转换到Native Runtime中执行,网络请求也不例外。同时WEEX也提供了自定义相应实现的接口,通过重写网络请求适配器,我们可以较为简单地接入HTTPDNS。在WEEX运行环境中,主要有两种网络请求:

  • 通过Stream进行的网络请求
  • <image>标签指定的加载图片的网络请求

下面以 weex iOS 0.7.0 版本为例:

Stream网络请求 + HTTPDNS

Stream网络请求在 iOS 端最终会通过WXNetworkDefaultImpl完成,同时WEEX也提供了相应的接口自定义网络请求适配器。具体的逻辑如下:

第一步:创建自定义网络请求适配器,实现 WXNetworkHttpDnsImpl 接口

#import <WeexSDK/WeexSDK.h>
#import "WXNetworkDefaultImpl.h"

@interface WXNetworkHttpDnsImpl : NSObject<WXNetworkProtocol, WXModuleProtocol , NSURLSessionDelegate>

@end

第二步:在WEEX初始化时注册自定义网络适配器,替换默认适配器:

    [WXSDKEngine registerHandler:[WXNetworkHttpDnsImpl new] withProtocol:@protocol(WXNetworkProtocol)];

之后的网络请求都会通过WXNetworkHttpDnsImpl实现,所以只需要在WXNetworkHttpDnsImpl中植入 HTTPDNS 逻辑即可,具体逻辑可以参考如下代码:

#import "WXNetworkDefaultImpl.h"

@interface WXNetworkCallbackInfo : NSObject

@property (nonatomic, copy) void(^sendDataCallback)(int64_t, int64_t);
@property (nonatomic, copy) void(^responseCallback)(NSURLResponse *);
@property (nonatomic, copy) void(^receiveDataCallback)(NSData *);
@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, copy) void(^compeletionCallback)(NSData *, NSError *);

@end

@implementation WXNetworkCallbackInfo

@end

@implementation WXNetworkDefaultImpl
{
    NSMutableDictionary *_callbacks;
    NSURLSession *_session;
}

- (id)sendRequest:(NSURLRequest *)request withSendingData:(void (^)(int64_t, int64_t))sendDataCallback
                                             withResponse:(void (^)(NSURLResponse *))responseCallback
                                          withReceiveData:(void (^)(NSData *))receiveDataCallback
                                          withCompeletion:(void (^)(NSData *, NSError *))compeletionCallback
{
    WXNetworkCallbackInfo *info = [WXNetworkCallbackInfo new];
    info.sendDataCallback = sendDataCallback;
    info.responseCallback = responseCallback;
    info.receiveDataCallback = receiveDataCallback;
    info.compeletionCallback = compeletionCallback;
    
    if (!_session) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                 delegate:self
                                            delegateQueue:[NSOperationQueue mainQueue]];
    }
    
    NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
    if (!_callbacks) {
        _callbacks = [NSMutableDictionary dictionary];
    }
    [_callbacks setObject:info forKey:task];
    [task resume];
    
    return task;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                                didSendBodyData:(int64_t)bytesSent
                                 totalBytesSent:(int64_t)totalBytesSent
                       totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.sendDataCallback) {
        info.sendDataCallback(totalBytesSent, totalBytesExpectedToSend);
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task
                                 didReceiveResponse:(NSURLResponse *)response
                                  completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.responseCallback) {
        info.responseCallback(response);
    }
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.receiveDataCallback) {
        info.receiveDataCallback(data);
    }
    
    NSMutableData *mutableData = info.data;
    if (!mutableData) {
        mutableData = [NSMutableData new];
        info.data = mutableData;
    }
    
    [mutableData appendData:data];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.compeletionCallback) {
        info.compeletionCallback(info.data, error);
    }
    [_callbacks removeObjectForKey:task];
}

@end

1.2 <image>网络请求 + HTTPDNS

WEEX并没有提供默认的图片适配器实现,所以用户必须自行实现才能完成图片请求逻辑,具体步骤分为以下几步:

第一步:自定义图片请求适配器,实现IWXImgLoaderAdapter接口

#import "WXImgLoaderProtocol.h"

@interface WXImgLoaderDefaultImpl : NSObject<WXImgLoaderProtocol, WXModuleProtocol>
@end

第二步:在WEEX初始化时注册该图片适配器:

   [WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];

所以同WXNetworkHttpDnsImpl一样,我们只需在WXNetworkHttpDnsImpl植入HTTPDNS逻辑即可。

相关文章
|
存储 Ubuntu Linux
在Linux中,如何查看当前主机的主机名,如何修改主机名?要想重启后依旧生效,需要修改哪个配置文件?
在Linux中,如何查看当前主机的主机名,如何修改主机名?要想重启后依旧生效,需要修改哪个配置文件?
|
算法 NoSQL 应用服务中间件
阿里面试:10WQPS高并发,怎么限流?这份答案让我当场拿了offer
在 Nacos 的配置管理界面或通过 Nacos 的 API,创建一个名为(与配置文件中 dataId 一致)的配置项,用于存储 Sentinel 的流量控制规则。上述规则表示对名为的资源进行流量控制,QPS 阈值为 10。resource:要保护的资源名称。limitApp:来源应用,default表示所有应用。grade:限流阈值类型,1 表示 QPS 限流,0 表示线程数限流。count:限流阈值。strategy:流控模式,0 为直接模式,1 为关联模式,2 为链路模式。
阿里面试:10WQPS高并发,怎么限流?这份答案让我当场拿了offer
|
Ubuntu 应用服务中间件 nginx
docker入门-快速学会docker
本文介绍了Docker的基本概念,包括镜像、容器、tar文件、Dockerfile和仓库,并通过实际操作演示了如何使用Docker。从拉取Nginx镜像、运行容器、修改容器内容、保存容器为新镜像,到使用Dockerfile构建自定义镜像,最后讲解了如何保存和恢复镜像。文中还推荐了一个在线实践平台Play with Docker,方便读者快速上手Docker。
1310 5
docker入门-快速学会docker
|
Oracle 关系型数据库 数据库
❤️Docker中只需2步即可拥有Oracle 11G企业版环境,史上最快部署❤️
❤️Docker中只需2步即可拥有Oracle 11G企业版环境,史上最快部署❤️
1936 0
❤️Docker中只需2步即可拥有Oracle 11G企业版环境,史上最快部署❤️
|
存储 应用服务中间件 数据库
服务器,你真的了解吗?
服务器是在网络中为其他计算机提供服务的高性能计算机,具备高速CPU运算能力、长时间稳定运行及强大的I/O能力。其主要组件包括CPU、内存、硬盘等,并通过自带管理系统进行数据控制。按外形分为塔式、机架、刀片和高密服务器;按指令集分为CISC(如x86)和RISC(如Unix、ARM);按处理器数量分为单路、双路和多路服务器;按负载类型则有数据库、应用、接入、Web和文件服务器等多种分类。每种服务器针对不同应用场景设计,满足多样化的计算需求。
|
机器学习/深度学习
清华领衔发布多模态评估MultiTrust:GPT-4可信度有几何?
【8月更文挑战第16天】近日,清华大学等机构发布了MultiTrust多模态评估研究,旨在全面评估大型语言模型的可信度。这是首个统一的多模态基准,覆盖真实性、安全性等五大方面,包含32个任务。研究对21个现代模型进行了实验,揭示了可信度问题和风险,强调了提高模型可靠性的重要性。结果显示开源模型在可信度上落后于专有模型,特别是在安全性方面。此外,研究还发现了模型在鲁棒性、公平性和隐私方面的挑战。论文已发布于arxiv.org。
569 1
|
机器学习/深度学习 数据采集 人工智能
AI在医疗:深度学习在医学影像诊断中的最新进展
【10月更文挑战第26天】近年来,深度学习技术在医学影像诊断中的应用日益广泛,通过训练大量医学影像数据,实现对疾病的准确诊断。例如,卷积神经网络(CNN)已成功用于识别肺癌、乳腺癌等疾病。深度学习不仅提高了诊断准确性,还缩短了诊断时间,提升了患者体验。然而,数据隐私、数据共享和算法透明性等问题仍需解决。未来,AI将在医学影像诊断中发挥更大作用,成为医生的得力助手。
1171 0
|
安全 网络架构
Ad-Hoc 和 Infrastructure 拓扑之间的区别
【8月更文挑战第24天】
694 0
|
机器学习/深度学习 自然语言处理 API
自然语言处理 Paddle NLP - 文本语义相似度计算(ERNIE-Gram)
自然语言处理 Paddle NLP - 文本语义相似度计算(ERNIE-Gram)
1100 0
|
前端开发 JavaScript 数据处理
深入Python Web开发:模板引擎的力量与最佳实践
【7月更文挑战第21天】Python Web开发中,模板引擎如Jinja2促进MVC架构的View层,分离后端数据与前端展示,提升开发效率和代码复用。选择适合的模板引擎,利用其数据注入、模板继承等特性,保持模板简洁,注重安全性,是最佳实践。例如,Jinja2允许在HTML中嵌入变量并处理循环,简化渲染过程。
462 0