程序调试 (八) —— 基于iOS的高级Charles Proxy教程(一)

版本记录

版本号 时间
V1.0 2021.07.20 星期二

前言

程序总会有bug,如果有好的调试技巧和方法,那么就是事半功倍,这个专题专门和大家分享下和调试相关的技巧。希望可以帮助到大家。感兴趣的可以看下面几篇文章。
1. 程序调试 (一) —— App Crash的调试和解决示例(一)
2. 程序调试 (二) —— Xcode Simulator的高级功能(一)
3. 程序调试 (三) —— Xcode Simulator的高级功能(二)
4. 程序调试 (四) —— Xcode内存管理(一)
5. 程序调试 (五) —— 使用Build Configurations 和 .xcconfig 构建你的App(一)
6. 程序调试 (六) —— 使用Build Configurations 和 .xcconfig 构建你的App(二)
7. 程序调试 (七) —— 基于iOS的Charles Proxy教程(一)

开始

首先看下主要内容:

通过学习将响应映射到本地文件、自动化请求和写入日志等高级功能,从 Charles Proxy 中获得更多。内容来自翻译

下面看下写作环境:

Swift 5, iOS 14, Xcode 12

下面就是正文了。

Charles Proxy 使开发人员和测试人员可以立即查看网络流量。 但是除了基础知识,还有很多东西需要学习。

如果您曾经不要求后端服务器更改响应数据而测试客户端、报告服务器端错误或在需要特定后端响应的客户端上重现状态,那么高级 Charles 代理功能提供了解决方案 .

在本教程中,您将在 StarCharles 应用程序中处理从 Star Wars API (SWAPI) 到您自己的自定义 API 的响应。 在此过程中,您将:

  • 建立Charles
  • 使用mapping tool and breakpoints
  • 使用rewrite and repeat tool执行重复操作。
  • 将网络活动保存到磁盘。
  • 与他人分享报告。

注意:本教程假设您熟悉 Charles Proxy。如果不熟悉,首先查看 iOS 的 Charles Proxy Tutorial for iOS教程。

下载项目材料。打开 starter 文件夹中的 StarCharles.xcodeproj

StarCharles 列出了星球大战的电影和角色,由 SWAPI 提供。 构建并运行以查看它是如何工作的。

在幕后,每次点击filmcharacter时,该应用程序都会发出一系列请求以获取接下来显示的信息。

在 Xcode 中查看以下组:

  • Network:包含 NetworkService.swift,它定义了所有的网络交互。
  • Models:包括所有数据模型。
  • ViewModel:包含ViewModel.swift,它是项目的核心。它调用所有 API,映射到本地模型并更新视图。
  • Views:包括所有与视图相关的代码。

现在,您将安装和配置 Charles Proxy 以观察 StarCharlesSWAPI之间的通信。


Setting up Charles

您的第一步是使 Web 调试设置正常工作。为此,您将:

  • 下载并安装Charles
  • Charles 自动配置您的网络设置。
  • SSL 证书下载并安装到要观察加密网络通信的每个模拟器或设备上。

首先,下载适用于 macOS 的最新版 Charles Proxy,在撰写本文时为 v4.6.1。双击 DMG 文件,接受许可协议并将 Charles 图标拖到您的 Applications 文件夹中进行安装。

Charles Proxy 不是免费的,但它提供 30 天的免费试用。由于 Charles 在试用模式下仅运行 30 分钟,因此您可能需要在整个教程中重新启动它。

1. Configuring Network Settings

启动Charles。 它应该请求允许自动配置您的网络设置。 如果没有,请按 Shift-Command-P 以查看此提示:

如果出现提示,请单击Grant Privileges并输入您的密码。 Charles 一启动就开始记录网络事件。 您应该已经看到事件弹出到左窗格中。

2. Installing SSL Certificates

Charles 介于 Web 浏览器和 API 之间。 它使用自己的根证书(root certificate)(也称为证书颁发机构 (CA))动态创建和签署它发送到本地浏览器的证书,让您以纯文本形式查看网络流量。

为此,您必须在要查看网络请求和响应的设备或模拟器中安装并信任 Charles 根证书。

转到运行 StarCharles 的模拟器。 打开 Safari,然后输入chls.pro/ssl

如果您没有看到此alert,则可能需要重新启动 Charles。 尝试一下,然后在模拟器上的 Safari 中重新加载网页。 点击Allow下载包含根证书的配置文件。

接下来,打开设置。 导航到 General ▸ Profile 并点击 Charles Proxy CA

点击右上角的蓝色安装Install按钮,然后在接下来的警告Warning屏幕上再次点击安装Install。 一旦您完全安装了包含 Charles Proxy CA 的配置文件,您的模拟器屏幕将如下所示:

最后,您需要完全信任此证书。 在模拟器上的设置中,转到常规 ▸ 关于 ▸ 证书信任设置(General ▸ About ▸ Certificate Trust Settings)

Enable Full Trust for Root Certificates下,打开 Charles Proxy CA 并在阅读根证书alert后点击Continue

构建并运行。 轻点Films,然后轻点特定的film。 接下来,点击一个character。 浏览应用程序以拨打一些网络电话。 查看您在 StarCharles 中点击的每一行如何显示对 Charles 中的 swapi.devCONNECT 请求。

恭喜,做到这一步意味着您已经成功地设置了 Charles。 步步高升!

注意:如果您在设置 Charles 时遇到任何问题,请查看 Charles Proxy Tutorial for iOSCharles FAQ 页面以获得更多帮助。


Focusing on a Host

默认情况下,Charles 会跟踪 Mac 上的所有网络调用。 现在,您只对一个特定的host感兴趣:https://swapi.dev/。 通过只关注这个域,您可以避免在 Charles 中看到每个网络请求时分心。

按照以下步骤专注于单个域:

  • 单击Sequence选项卡以按时间顺序显示网络调用。
  • 右键单击任何 swapi.dev 请求,然后单击下拉菜单中的 Focus
  • 选中 Filter 字段右侧的 Focused 以将显示的流量限制为仅对 swapi.dev 的调用。

这样,您就向focus列表添加了一个域名。 您可以随时禁用Focus过滤器并选择要关注的任何其他域。

注意:通过按 Shift-Command-O,您可以查看Focused Hosts列表、添加或删除域以及导入和导出此列表。


Enabling SSL Proxying

查看其中一个 swapi.dev 请求中的内容。 选择任何请求,然后单击屏幕下方的 Contents 选项卡。 哇,那是什么?

注意:如果您看到RequestResponse而不是Contents,请单击其中之一。 这只是意味着您在 Charles Preferences 对话框的 Viewers 选项卡中取消了Combine request and response

如果请求的内容出现乱码,则需要启用SSL proxying。 这会告诉 Charles 使用您之前安装的根证书与您启用 SSL 代理的域进行通信。 去做这个:

  • 1) 右键单击任何 swapi.dev 请求,然后从下拉菜单中选择Enable SSL Proxying
  • 2) 退出并重新启动Charles
  • 3) 打开Proxy ▸ SSL Proxying Settings。 确认 swapi.dev 显示为 SSL Proxying中包含的位置。
  • 4) 点击 Charles 主窗口中的小扫帚扫除现有网络流。 然后,在 StarCharles中进行网络呼叫。
  • 5) 现在,选择任何 swapi.dev 请求并选择 Contents 选项卡。

啊,好多了!

探索所有内容窗格选项卡以更深入地了解Star Wars


Manipulating Data

Charles 提供了多种用于处理请求和响应数据的工具,包括:

  • Map Local
  • Map Remote
  • Rewrite
  • Mirror
  • Auto Save
  • Repeat
  • Advanced Repeat

注意:您可以在 Charles documentation中查看所有工具。

1. Mapping Requests to Local and Remote Responses

Charles 中,mapping允许您更改请求,以便从新位置透明地提供其响应,就好像它是原始响应一样。 事实上,数据实际上是从其他地方到达的,比如另一台主机甚至本地文件。

这意味着您可以根据自己的喜好模拟您的响应并操纵数据,然后查看您的应用程序如何处理更改。 例如,如果变量的类型从 Int 更改为 String,您的应用程序将如何运行? 如果一个值意外为nil怎么办? 您可以轻松测试这些问题。

Map Local 工具映射单个请求以从本地计算机而不是通常的端点获取响应。 接下来,您将在 StarCharles 中试用它。

在下载的项目材料中,您将找到一个包含films.json 的资源文件夹。 使用以下步骤将 https://swapi.dev/api/films/映射到 film.json

  • 在模拟器上的 StarCharles 应用程序中,点击Films
  • Charles 中,右键单击 https://swapi.dev/api/films/ 并选择 Map Local
  • 单击Choose。 从下载的资料中选择films.json的目的地。 单击OK
  • 打开模拟器。 从当前屏幕返回。 点击Films

您只需映射一个请求即可获得自定义的本地响应。 结果,您拥有相同的数据模型,但具有不同的值。

从这一点开始,您可以操作films.json 来包含您想要的任何值。 但是,请注意数据模型,以避免将错误引入应用程序。

Map Remote Tool

正如 SWAPI 的狂热粉丝已经知道的那样,没有人维护原始的 swapi.co。 然而,幸运的是,SWAPI 的副本存在于银河系的其他地方。 在本节中,您将使用 Map Remote 工具在 StarCharles 使用的副本 swapi.dev 和不同的副本 swapi.tech 之间进行映射。

使用以下步骤映射 https://swapi.dev/api/people/ 请求以从 https://www.swapi.tech/api/people/获取其响应:

  • 点击 StarCharles 中的 Characters 以生成 https://swapi.dev/api/people/
  • 右键单击 Charles 中的请求并选择 Map Remote。 保持 Map From 部分不变,然后像这样填写下面的 Map To 部分:
    • 选择 https 作为协议。
    • 填写 www.swapi.tech 作为 Host
    • 在端口中输入 443
    • 输入 /api/people/ 作为Path
    • 单击OK以保存映射。
  • 返回模拟器,点击 StarCharles 返回应用程序的顶层,然后点击 Characters。 不好了! 我们怎么知道卢克长什么样?

正如您在 Charles 中看到的,请求现在发送到一个新host。 由于新host使用稍微不同的数据模型,因此响应现在仅包含字符名称。

View All Mappings

要查看映射请求列表,请执行以下步骤:

  • 打开Tools菜单。
  • 单击 Map Local 查看映射到您计算机上位置的请求。
  • 或者,单击 Map Remote 以查看映射到不同host的请求。

您可以双击任何映射进行编辑或使用显示的按钮添加新映射、重新排序映射列表、从其他地方导入映射或导出当前映射。

注意:映射设置会影响 StarCharles 显示的数据。如果在后面的部分中没有看到预期的结果,请检查是否需要启用或禁用本地或远程映射。

2. Using Breakpoints

试图解决后端问题?通过使用断点和处理空中数据,您可以模拟可能来自后端服务器的任何状态。

在本节中,您将通过在 https://swapi.dev/api/people/1 及其相应响应上添加断点来尝试此操作。在开始之前,通过转到Tools ▸ Map Remote并取消选中Enable Map Remote来关闭您在上一节中设置的远程map。保留本地映射;你会在这里使用它。

按照以下步骤在 https://swapi.dev/api/people/1 请求及其相应响应上添加断点。

  • StarCharles 中打开Films
  • 点击LOCAL A New Hope
  • Charles 中右键单击请求 https://swapi.dev/api/people/1 并选择 Breakpoints
  • 返回模拟器并再次打开LOCAL A New Hope
  • 现在,您可以在请求到达后端之前使用任何输入更改请求的字段。
  • 单击Execute。第一次用于发送请求。
  • 单击Execute。第二次为请求响应。

执行此操作时,您在特定 API 调用上放置了一个断点。 然后,您可以在向实际服务器发出该请求之前捕获该调用,并且您可以操作发送的请求。 您还可以更改在到达客户端之前来自后端的确切响应 - 在本例中为 StarCharles

注意:如果您错过了响应,您的请求很可能因为超时而失败。 尝试更快地进行更改。

要停止使用断点捕获请求,请转到Proxy ▸ Disable Breakpoints

要查看带有断点的所有请求的列表,请打开Proxy ▸ Breakpoint Settings

3. Filtering Requests with Allow and Block Lists

在本教程的前面部分,您学习了如何关注特定host。 现在,您将学习如何制作一个列表以允许或阻止请求。 如果您想模拟服务器错误或连接丢失的情况,这会派上用场。

按照以下步骤将 https://swapi.dev/api/people/2 添加到阻止列表:

  • StarCharles 中打开Films
  • 点击LOCAL A New Hope
  • Charles 中右键单击 https://swapi.dev/api/people/2 并选择Block List
  • 返回模拟器并再次打开LOCAL A New Hope

通过这样做,您将该请求放在block list中。 Charles 会一直失败,你会在 Xcode 控制台中看到以下错误:

Fetch character completed: failure(StarCharles.NetworkError.jsonDecodingError(error: Foundation.URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1 "(null)")))

您可以通过在 Charles 中再次右键单击此请求来禁用block,然后在下拉菜单中取消选中Block List

注意:通过将任何请求添加到allow list,您将创建一个white listCharles 现在将阻止除allow list中的请求之外的所有请求。

您可以通过选择Tools ▸ Allow List 或者 Tools ▸ Block List来查看添加到允许或阻止列表的所有请求的列表。 您也可以在此处修改该列表。


Automating Actions

既然您知道如何使用断点操作请求和响应,您可能想知道是否有一种方法可以做到这一点,而无需打开断点编辑窗格并每次都争时间的地手动更改响应。

有! 在本节中,您将学习如何为repetitive actions编写规则。

这不仅可以节省时间,还可以帮助那些对您的应用程序没有相同访问权限的测试人员。 例如,假设测试人员想要使用特定token试用您的应用。 在这种情况下,他们不需要为所有请求添加断点。 相反,他们可以使用Rewrite工具使用规则修改所有请求上的token

使用Rewrite工具,您可以创建规则来修改通过 Charles 的请求和响应。

Charles 菜单栏中,单击Tools ▸ Rewrite。 选中Enable Rewrite,然后单击Add以查看工具的所有三个部分:sets, locations and rules

  • 1) Sets:如左侧所示,每个can可以有不同的locations和不同的rules
  • 2) Locations:显示在右上角,每个locations都包含destination host的规范。
  • 3) Rules:显示在右下角,每个规则都包含实际的重写操作,您可以在其中操作请求和响应的以下属性:
  • Header
  • Host
  • Path
  • URL
  • Query Parameters
  • Response Status
  • Body

接下来,您将尝试一下。

1. Rewriting Responses in Action

还记得您映射 https://swapi.dev/api/people/ 以获取来自 https://www.swapi.tech/api/people/ 的响应吗?

假设您是一名黑客,他想要使用中间人服务器来接收所有请求并收集数据,并使用与客户端预期的相同结构但使用不同的值对其进行响应。 您已经将原始服务器映射到新服务器; 现在,是时候用替换来重写所有请求了。

在本节中,您将重写该请求,以便它不是从 swapi.tech 获取people,而是获取planets

  • 删除占位符set(如果有)。
  • Charles 中,打开Tools ▸ Rewrite
  • 选中Enable Rewrite
  • 单击Add以添加新set并将其命名为 People
  • Location下,单击Add并将 https://swapi.dev/api/people/ 粘贴到host文本框中以自动填充其他文件。 确保在people之后包含最后的斜线。 单击OK
  • 在规则rules部分,添加一个Path类型的新规则。 在Match下的Value字段中输入people,在Replace下的Value字段中输入planets
  • 单击OK保存新规则,然后再次单击OK保存并关闭Rewrite Settings
  • 在模拟器中,点击Characters

如您所见,结果与以前不同。 当然,人们可能会争辩说,planets本身也是characters

2. Repeating Requests

当您测试后端代码时,您可能希望在不涉及客户端的情况下检查服务器的响应。 Repeat工具使这变得容易。 通过右键单击任何请求,然后选择Repeat来启用它。

在这种情况下,Charles 向服务器重新发送完全相同的请求,并将响应作为新请求显示给您,而无需对您的客户端执行任何操作。 默认情况下,这只会发生一次。

当很难导航到客户端界面中发送请求的位置时,请记住Repeat工具。 一旦您有一个示例请求,请使用Repeat发送它。

注意:您可以使用 Repeat Advanced 获得更多选项,例如迭代次数和并发性,hook可能来自后端的错误。


Recording Network Activity

通过记录网络活动并将其保存到磁盘,您可以比较一段时间内的结果。 这让您可以查看您的后端团队是否对您的服务器进行了任何更改。

如果您想将任何结果作为测试人员或作为在特定请求中发现安全问题的黑客传递任何结果,这也可以让您制作一些报告。

1. Mirroring Network Data Locally

使用 Mirror,您可以将会话的响应保存到磁盘。 这有助于:

  • 将数据从一台服务器迁移到另一台服务器。
  • 制作所有responses的副本。
  • 克隆服务器以在本地使用。

Charles 将响应放置在 API 本身使用的相同目录结构中。 这意味着对于与 URL 具有相同文件名的每个响应,您将拥有相同的路径。 请注意,文件名包括查询字符串。

注意:如果您收到针对同一个 URL 的两个响应,Charles 将覆盖新的响应,因此除非您关闭该工具,否则您将始终在镜像中保存最新的响应。

要启用镜像,请执行以下操作:

  • Charles 中,打开Tools ▸ Mirror
  • 选中Enable Mirror
  • 选中Only for selected locations
  • 选择一个保存目的地。
  • 通过在host字段中输入 https://swapi.dev/api/* 添加一个新位置,然后单击另一个字段进行自动填充。 单击OK

现在您已将 Charles 设置为将来自 swapi.dev 的所有响应镜像到您的磁盘,返回模拟器中的 StarCharles 并四处导航以生成一些流量。

Finder中,打开保存目的地。

现在,您可以看到保存的会话响应。

2. Automatically Saving Sessions

如今,大多数开发人员使用 Charles 或其他代理来监控他们与服务器的交互。但是,有时真的很难找到导致问题的特定请求和会话。这可能是因为您清理了Charles 会话视图,或者因为弹出了许多不同的请求。

假设您有一个测试人员,他使用 Charles 设置在多个设备上并行运行前端测试。在这种情况下,测试人员应该能够看到结果并在出现错误时轻松做出报告。通过使用Auto Save工具,测试自动化的管道变得更加简单。

使用此工具,Charles 会自动保存和清除任何时间段的记录会话。

要启用此功能,请按照以下步骤操作:

  • Charles 中,打开Tools ▸ Auto Save
  • 选中Enable Auto Save
  • 输入 2 作为保存间隔。这告诉Charles每两分钟保存一次。
  • 选择一个目的地来保存数据。
  • 对于本教程,将Save type保留为 Charles Session File。但是,请查看所有其他选择,以了解对您的用例有意义的内容。

CharlesyyyyMMddHHmm 格式保存名称中带有时间戳的会话文件,因此它们会按时间顺序出现在您选择会话的位置。

StarCharles 中四处导航。 等待几分钟,您将在保存目标中看到保存的会话。

您可以使用这些文件制作报告并与任何人共享。他们可以在 Charles 中打开文件并查看与您在此处生成的完全相同的会话。

注意:Auto SaveMirror保存会话中的不同信息。Auto Save保留所有内容,所有请求和响应。 Mirror 仅保留您从服务器收到的作为响应的输出数据。


Using Charles in a Team

Charles 提供了多种功能来帮助测试人员和开发人员协同工作。您已经了解了使用 Auto Save 共享会话,但还有其他方法可以将 Charles 数据发送给其他人。您还可以发送您的 Charles 设置或导入其他人的设置,以便测试团队的所有成员都可以使用相同的设置。

1. Sharing Sessions

Charles 中,当您右键单击其中一个请求时,您会看到以下选项:

  • Copy URL:复制实际 URL。
  • Copy cURL Request:复制包含请求的所有数据(包括标头)的 cURL 请求。
  • Copy Response:复制响应内容。
  • Save Response:保存响应内容。
  • Export Session:以您选择的格式导出整个会话。

注意:为了最好地帮助后端开发人员准确了解发生了什么,请发送整个会话或 cURL 请求和相应的响应。

2. Sharing Settings

您可能已经注意到,Charles 提供了几乎所有内容的导入和导出选项,尤其是工具的配置。 尝试以下任一方法以从 Charles 共享工具配置:

  • 1) 当您从菜单栏中打开任何工具时,您最终会进入一个包含两个选项的窗口,即ImportExport。 这使您可以在特定工具(specific tool)中执行操作。
  • 2) 您还可以打开Tools ▸ Import/Export Settings。 选择是要导入还是导出设置。

注意:在下载的项目资料中,您可以在资源文件夹中找到Charles Settings.xml,您可以将其导入您的Charles。 它包括您在本教程中使用的所有配置。

恭喜! 现在您已经完成了本教程,您对 Charles Proxy 的一些更高级的功能有了更深入的了解。

在本教程中,您学习了如何:

  • 使用Charles作为代理观察网络,并顺便rewrite数据。
  • 使用映射和断点来操作数据。
  • 添加不同的规则集来rewrite请求和响应。
  • 将所有网络活动保存到磁盘。
  • 与他人分享报告。

如果您想更深入地探索,请从这里查看 Charles documentation。 有关 iOS 网络的更多信息,请查看 Networking with URLSession网络视频课程。

后记

本篇主要讲述了iOSCharles Proxy教程,感兴趣的给个赞或者关注~~~

推荐阅读更多精彩内容