chromium 协议栈 cronet ios 踩坑案例

1、请求未携带 Accept-Language http header 出现图片加载失败

现象:
访问 https://www.huawei.com/cn/?ic_medium=direct&ic_source=surlent 时出现图片加载失败的问题
在这里插入图片描述
预期结果:
在这里插入图片描述

原因:
网络库删除了添加 Accept-Language header 的逻辑,华为商城站点的图片 server 发现请求未携带该 header 直接返回403。

解决方案:
补充对该 header 的添加逻辑,请求未携带该 header 时网络库自动根据手机设置的语言环境添加。

+ (NSString*)getAcceptLanguagesFromPreferredLanguages:
    (NSArray<NSString*>*)languages {
  NSMutableArray* acceptLanguages = [NSMutableArray new];
  for (NSString* lang_region in languages) {
    NSString* lang = [lang_region componentsSeparatedByString:@"-"][0];
    if ([lang_region rangeOfString:@"zh-Hans-CN"].location != NSNotFound) {
      lang = @"zh-CN";
    } else if ([lang_region rangeOfString:@"zh-Hant-"].location != NSNotFound) {
      // 台湾、香港、澳门、繁体统一用繁体
      lang = @"zh-TW";
    }
    NSString* localeAcceptLangs = acceptLangs[lang_region] ?: acceptLangs[lang];
    if (localeAcceptLangs)
      [acceptLanguages
          addObjectsFromArray:[localeAcceptLangs
                                  componentsSeparatedByString:@","]];
  }

  NSString* acceptLanguageString =
      [[[NSOrderedSet orderedSetWithArray:acceptLanguages] array]
          componentsJoinedByString:@","];
  return [acceptLanguageString length] != 0 ? acceptLanguageString
                                            : @"en-US,en";
}

+ (NSString*)getAcceptLanguages {
  return [self
      getAcceptLanguagesFromPreferredLanguages:[NSLocale preferredLanguages]];
}

2、server 下发多个 content-type 时出现页面乱码

正常情况下 server 下发的 content-type 只有一个,但少数不规范站点下发了多个且互斥的 value,而预期的可能是最后一个,而 在该情况下,cronet 一般只会取第一个 value 返回,因此可能出现页面乱码的问题:

// 不规范content-type示例,该 header 会引起下面的乱码页面
content-type: text/html; charset=utf-8, text/html; charset=gbk 

在这里插入图片描述
解决方案:
修改 ios/net/protocol_handler_util.mm 的 GetNSURLResponseForRequest 方法中处理 content-type 的部分,针对域名分策略处理,比如策略一,cronet 将 server 下发的所有 content-type 返回给上层;策略二,cronet 将最后一个 content-type 返回给上册,否则按默认处理(即只返回第一个)。
cronet 官方源码:https://source.chromium.org/chromium/chromium/src/+/main:ios/net/protocol_handler_util.mm;l=132
在这里插入图片描述

3、业务请求携带的 referer header 过长导致页面白屏问题

当请求携带的 referer 过长时(> 4KB),cronet 会移除该 header,如果server 端认为未携带 referer 的请求非法时会导致请求失败,从而出现浏览器页面白屏现象。

解决方案:
在 net/url_request/url_request.cc 的 URLRequest::StartJob 方法中处理 referer 的部分,增加域名白名单机制,域名白名单的域名在出现 referer 过长时,将 referer 改为仅保留 host 信息,而不是全部删除,例如:

过长 referer:https://source.chromium.org/chromium/chromium/src/+/main:net/url_request/url_request.cc(假设它超过 4KB)
处理后 referer:https://source.chromium.org

在这里插入图片描述

关于 http referer 长度限制原因:
在这里插入图片描述
主流浏览器对上述长度限制的支持情况:
在这里插入图片描述

4、server 与客户端压缩算法协商不一致出现访问错误

现象:
访问 www.berkshirehathaway.com 站点出现失败情况:
在这里插入图片描述
原因:
网络库在设置 accept-encoding 时未添加 br 压缩的支持,而 server 响应的内容为 br 压缩的,因此出现该错误页面。cronet 对应的内部错误码为 -330:

// Content decoding of the response body failed.
NET_ERROR(CONTENT_DECODING_FAILED, -330)

需要修改 net/http/http_network_transaction.cc 文件 HttpNetworkTransaction::ContentEncodingsValid 方法,如果 server 响应内容为br 压缩,而请求未支持 br 时,按 br 解压:

  ...
  // Temporary workaround for http://crbug.com/714514
  if (headers->IsRedirect(nullptr)) {
    return true;
  }

  /* 以下为修复代码 */
  if (!result && (content_encoding.find("br") != std::string::npos) &&
      (accept_encoding.find("br") == std::string::npos)) {
        result = true;
  }

在这里插入图片描述

  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cronet和OkHttp都是用于网络请求的库,但它们有一些区别。 1. 架构和用途: - Cronet是Google开发的网络库,它是基于Chromium网络栈构建的,主要用于Android平台上的网络请求。Cronet提供了高性能和低延迟的网络请求能力,并且支持HTTP/2和QUIC等协议。 - OkHttp是Square开发的网络库,它是基于Java语言构建的,可以在Android和Java平台上使用。OkHttp提供了简洁易用的API,支持HTTP/1.1和HTTP/2协议,并且具有连接池、请求拦截器、缓存等功能。 2. 性能和功能: - Cronet在性能方面具有优势,它使用了Chromium网络栈,可以利用Chromium在网络请求方面的优化和经验。Cronet支持并发请求、请求优先级管理、请求流量控制等功能,可以满足高性能网络请求的需求。 - OkHttp也是一个高性能的网络库,它使用了连接池和异步请求等技术来提高性能。OkHttp支持请求重试、连接超时、连接池管理等功能,并且可以通过拦截器来实现自定义的网络请求处理逻辑。 3. 兼容性和依赖: - Cronet是Google官方推荐的网络库,但它目前仅在Android平台上可用,并且需要导入相应的Cronet库文件。 - OkHttp是一个跨平台的网络库,可以在Android和Java平台上使用,并且可以通过Gradle等构建工具方便地引入依赖。 总的来说,Cronet和OkHttp都是优秀的网络库,选择使用哪个取决于具体的需求和平台限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值