Whistle proxy

由於我们在上一篇已经完成了成功载入班次的部分,接下来要做的当然是不正常的情况。虽然港铁间中会有事故,但都可遇不可求。要检查我们做的东西是不是正确除了写自动化测试之外,既然我们都做到 UI 的部分那就当然要直接看实物更好吧。所以我们先换一换题目讨论 proxy server。

Proxy server 是我们常用的工具,我们能用 proxy server 检查 app 的 HTTP request(这个之前介绍的 Flipper 都做到),亦能改变 response 令它变成我们想要的东西。这就可以令我们的 app 显示到事故、延误等画面。这次我们会以 Whistle 作示范,特色是它是免费而且是跨平台都能使用。其实市面上有很多选择,例如 CharlesProxymanFiddler 等等,用法都是大同小异。例如如何安装根证书、系统或浏览器设定 proxy server 都是跟平台(例如 Android、iOS、Windows、macOS 等等)而不是跟 proxy server。而 proxy server 部分只需要知道其中一个 proxy server 检视穿过 proxy server 的 HTTP traffic 以及何如改变 HTTP request 和 response 就应该很容易掌握到其他 proxy server 的用法。

安装 Whistle proxy server

Whistle 是用 Node 写的,所以要先在系统安装 NodeNPM。如果你用 Node 比较多的话,建议经 NVM 安装(POSIX 版Windows 版)。安装 Whistle 的方法就是用 NPM 安装:

npm install -g whistle

启动及终止 Whistle proxy server

安装後,可以在 terminal 用 w2 指令启动 Whistle:

PS C:\Users\Eric> w2 start
[i] [email protected] started
[i] 1. use your device to visit the following URL list, gets the IP of the URL you can access:
       http://127.0.0.1:8899/
       http://192.168.1.207:8899/
       http://192.168.98.1:8899/
       http://192.168.198.1:8899/
       Note: If all the above URLs are unable to access, check the firewall settings
             For help see https://github.com/avwo/whistle
[i] 2. configure your device to use whistle as its HTTP and HTTPS proxy on IP:8899
[i] 3. use Chrome to visit http://local.whistlejs.com/ to get started
PS C:\Users\Eric>

它会显示好几个网址,这个就是 Whistle 网页界面的网址。Proxy server 的 IP 和 port 就是这些网址的 IP 和 port。你可以视乎网络界面选用对应的 IP。

要停止 Whistle proxy server,只需使用 w2 stop

PS C:\Users\Eric> w2 stop
[i] whistle killed.
PS C:\Users\Eric>

如果是用 Windows 10 的话,可能会因为 execution policy 限制而无法启动 Whistle,遇到这个情况可以参阅 PowerShell 的 about_Execution_Policies 文档更改设定。

在 Android 安装根证书

由於 HTTPS 是加密的,要让 proxy server 看到传输的内容就要先为装置安装根证书。首先用装置的浏览器开启刚才 w2 start 看到的网址。

然後按顶部选单的「HTTPS」,就会开到下面的页面。只要按下「Download RootCA」就能下载根证书。

留意 Capture TUNNEL CONNECTs 有没有剔选,要剔选 Whistle 才能看到 HTTPS 的 traffic。

https://ithelp.ithome.com.tw/upload/images/20211007/20139666cjmhGqxhF2.png

然後到系统设定 > Security > Advanced > Encryption & credentials > Install a certificate。之後选取 CA certificate。

https://ithelp.ithome.com.tw/upload/images/20211007/2013966632lkcQpkQT.png

之後会看到一个警告画面,点选 Install anyway,再选取之前下载的 crt 档就能安装。

https://ithelp.ithome.com.tw/upload/images/20211007/20139666mgv5iBwMie.png

设定 proxy server

安装根证书之後就可以到 Wi-Fi 设定,Proxy 选取 Manual 就会弹出几个文字框让你填写 Proxy hostname 和 Proxy port。只要填上 w2 start 看到的 IP 和 port 就可以了。留意 127.0.0.1 那个是 localhost,在 Android 装置填这个几乎肯定是不能用的,填完後按 Save。

https://ithelp.ithome.com.tw/upload/images/20211007/20139666FwA3TfbZ76.png

之後可以试试用浏览器载入一些 HTTPS 网站,试试能不能正常载入,并且留意 Whistle 网页界面有没有东西弹出来,如果有就代表设定完成。

当用完後紧记还原这个设定,否则 Whistle 结束後 Wi-Fi 就不能用。

查阅 HTTP request

只需要在左边的导航栏选取 Network 就能查阅穿过 proxy server 的 HTTP traffic。点击想看的 request,右边上下两格就会显示该笔纪录的 request 和 response。

https://ithelp.ithome.com.tw/upload/images/20211007/20139666hrp5ZmPGHN.png

最底深灰色的输入栏是用来筛选 HTTP traffic,可以输入一些字眼来令上面只显示想查看的 HTTP traffic。

改变 HTTP request/response

刚才的查阅是最基本的功能,现在看看进阶一点的功能:把 HTTP request/response 变成自己想要的效果。这个功能主要用到的情景有:

  1. backend 未做完,但 client side(例如 Android app)想试试自己那边接驳 backend 的效果
  2. client side 想试一些难出现的效果或者情景,而这些效果或者情景是跟据 backend 的 response 决定

首先,我们要切换到 Rules 界面(在左边导航栏),你会看到一个蓝色的画面。这个是用来输入改变 request/response 规则的地方。在左边导航栏和蓝色输入规则的地方之间有一栏,这个是规则分组栏。你可以把它理解为规则是放在多个档案(分组)内,你可以分别启用和停用某些档案所写的规则。预设已经为你准备了一个空白的 Default 档案,你可以把规则分门别类地放,这样就容易整理。Default 旁边有个绿色剔号,意思是它目前生效中,点两下就可以把它停用。

https://ithelp.ithome.com.tw/upload/images/20211007/20139666eD1ZcRmSfS.png

现在先看看最简单的一个写法:把整个网站转去另一个网站。以下是把 google.com 转址去 apple.com:

google.com apple.com

填好後要按 Ctrl + S 或者上方的 Save 才会生效。

如果你在浏览器输入 google.com/hi,你就会看到它会转址到 apple.com/hi。如果切换到 Network 看的话,proxy server 是做了 HTTP 301 转址。

如果是 local 都有 server,想把 app 由 production server 转驳去自己的 server,可以这样写:

example.com 127.0.0.1

如果已经预先准备好 response 档案的话,可以直接指向本地档案:

# macOS, Linux
example.com file:///User/foo/bar.json
# Windows
example.com file://D:\foo\bar.json

另一个做法是把内容放到 Whistle 的 values,然後引用它。首先在左边导航栏点选 Values,这次的界面跟 Rules 有点像。先按 Create 并填上档案名称 delay.json。然後在蓝色背景的编辑器填上内容:

{
  "status": 0,
  "message": "Special train service arrangements are now in place on this line. Please click here for more information.",
  "url": "https://www.mtr.com.hk/alert/alert_title_wap.html",
  "curr_time": "2019-06-13 17:34:58"
}

https://ithelp.ithome.com.tw/upload/images/20211007/201396667AsB1DEvha.png

填好後按 Ctrl + S 或者上方的 Save 储存。

然後切换到 Rules 并写上我们要的 rule:

https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php resBody://{incldent.json}

这样每次 call endpoint 都会回传事故,这样就可以人工测试到 app 能否顺利因应 response 内容显示对应的画面。

要留意一样东西是用了 resBody:// 操作符虽然改了 response body,但其实还是会把 request 送上 server,如果那个 request 是用来建立或者删除内容的话就可能会影响到 backend 背後的 database 内容。如果要防止把 request 送上原本的 server 的话,其中一个方法是转用 file:// 操作符,另一个方法是额外加上 status:// 操作符:

https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php status://200 resBody://{incldent.json}

同一个网址可以套上多个操作符,其实开首的网址都不一定是网址,实际上是匹配规则 (pattern)。当它匹配後 Whistle 就会为那个 request 套上後面的操作符。匹配除了用普通的网址外,还可以用 regular expression,详细可以参考 Whistle 文档有关匹配模式的部分

除了改 status code 和 response body 之外,Whistle 还可以改 response header 和延长 response 回传时间:

https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php statusCode://200 resDelay://4000 resHeaders://{resHeaders.txt} resBody://{incident.json}

resDelay://4000 意思是把 response 传回去的时间延长多四秒,而 resHeaders://{resHeaders.txt} 的意思是 response header 换成放在 values 的 resHeaders.txt 的内容。下面是 resHeaders.txt 的内容:

Content-Type: application/json

快速开关 Android proxy 设定

先前介绍从 Wi-Fi 设定改变 proxy 设定,但步骤繁复。如果想简单一点可以用 Proxy Toggle 这个 app。它提供了 widget 让你放到主画面一键开关 proxy 设定。但安装和移除 app 要用到 adb(因为要改变系统设定,但不用 root)。特别留意在移除 app 前必须执行它提供的 adb 指令确保系统 proxy 设定被还原(因为不能从系统 UI 变更)。

https://ithelp.ithome.com.tw/upload/images/20211007/201396665MLUBEDaGU.jpg

Android app 允许用户加入的证书

自 Android 7 (API 24) 开始,app 可以在 manifest 的 <application> 加上 android:networkSecurityConfig 设定是否允许非 HTTPS traffic 和信任的证书以加强保安。由於我们用了自行签发的证书,所以要先更改预设设定才能用 proxy server 检阅 app 的 HTTPS traffic。首先在 manifest 的 <application> 加上 android:networkSecurityConfig

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.swiftzer.etademo">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name=".EtaDemoApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:networkSecurityConfig="@xml/network_security_config"
        android:theme="@style/Theme.ETADemo">
        <!-- 略 -->
    </application>
</manifest>

然後分别在 debug 和 main 的 source set 加上 network_security_config.xml

首先是 debug 版,下面的 XML 路径是 app/src/debug/res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:tools="http://schemas.android.com/tools">
    <base-config cleartextTrafficPermitted="false">
        <trust-anchors>
            <certificates src="system" />
            <certificates
                src="user"
                tools:ignore="AcceptsUserCertificates" />
        </trust-anchors>
    </base-config>
</network-security-config>

首先是 main (release) 版,下面的 XML 路径是 app/src/main/res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

这样就可以在 debug 版的 app 用 proxy server 了。

小结

本篇示范了用 Whistle proxy server 做一些简单的 request/response 处理和在 Android app 允许非系统预载的证书。这样在下一篇继续做班次页的各式错误页时就能用 proxy server 改变 response 来测试 app 的效果。此外,proxy server 是 frontend(包括 web 和 mobile)常用工具。了解 proxy server 基本用法能方便日常的开发(例如在陌生的 project 可以透过观察 HTTP traffic 然後搜寻到对应的 code 位置)。Whistle 有太多功能,这次只是介绍了它的皮毛,详细的用法还是需要参阅完整的文档


<<:  DAY 25 Big Data 5Vs – Veracity(准确性) Athena(2)

>>:  [Day 29] Trivy - 介绍、操作与导入CI/CD

伸缩自如的Flask [day9] request

在这里多看一下request,在前面的几篇文章中我们已经看过了他的身影,这里我们可以看一下它不同的属...

D3JsDay27What's the tree?Let me see—树状图(tree diagram)

树状图介绍 以下节录自维基百科树状结构 树状结构(英语:Tree structure),又译树形结构...

想要拿到更多的分红,且无脑的完成任务

不要做没意义的事情来侵蚀自己的热忱 图形介面固然好用,但反覆操作同样的SOP,1次、10次,甚至是1...

OpenTelemetry 与 Jaeger 应用 - 2

我们使用 github 上的 docker-compose.yml 进行建置。最後的容器回如下 do...

[DAY16]模板按钮

TemplateSendMessage - ButtonsTemplate buttons_temp...