[Lua] 使用 lua-zlib 套件,解開 gzip 壓縮後的資料
之前使用 lua-http 套件,連線 HTTPS 網站並取得回應內容,
結果後來遇到一個網站,它回傳的 Content-Encoding 是 x-gzip,
因此收到的 body 部分事實上是 gzip 編碼的。
這要怎麼解開呢?
當然如果存成檔案,再用命令列 gunzip
指令是可以解開,
不過我想在 Lua 程式裡直接解開,再做後續的處理…
查了一下,有人說 gzip 的壓縮格式和 zlib 的很像。
因此,去找了 lua-zlib 這個套件來試試看~
1. 安裝 lua-zlib 套件
用 luarocks 安裝 lua-zlib 套件,結果出現找不到 zlib 標頭檔的訊息:
$ sudo luarocks install lua-zlib Installing https://luarocks.org/lua-zlib-1.2-1.rockspec Cloning into 'lua-zlib'... remote: Enumerating objects: 17, done. remote: Counting objects: 100% (17/17), done. remote: Compressing objects: 100% (13/13), done. remote: Total 17 (delta 0), reused 10 (delta 0), pack-reused 0 Receiving objects: 100% (17/17), 17.51 KiB | 358.00 KiB/s, done. Note: switching to 'a305d98f473d0a253b6fd740ce60d7d5a5f1cda0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c <new-branch-name> Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false Error: Could not find header file for ZLIB No file zlib.h in /usr/local/include No file zlib.h in /usr/include No file zlib.h in /include You may have to install ZLIB in your system and/or pass ZLIB_DIR or ZLIB_INCDIR to the luarocks command. Example: luarocks install lua-zlib ZLIB_DIR=/usr/local
zlib 的標頭檔,哪邊找的到呢?
上網查了一下,說 Mac 上有裝 Xcode 的話就會有,
可以執行 xcrun --show-sdk-path
看 SDK 的路徑:
$ xcrun --show-sdk-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
這個路徑下面,有個 usr 目錄,
它下面的結構就很像一般 Linux 的 /usr 目錄,
會有 bin, include, lib 這些目錄:
$ ll /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -rw-r--r-- 1 root wheel 127 Mar 16 2021 Entitlements.plist -rw-r--r-- 1 root wheel 4512 Mar 16 2021 SDKSettings.json -rw-r--r-- 1 root wheel 3691 Mar 16 2021 SDKSettings.plist drwxr-xr-x 4 root wheel 128 Mar 16 2021 System/ drwxr-xr-x 7 root wheel 224 Mar 16 2021 usr/
在 usr/include 目錄下,就會看到 zlib.h 這個標頭檔。
因此我們可以將這個 usr 目錄,傳進 ZLIB_DIR 參數,
就可以成功用 luarocks 安裝 lua-zlib 套件了:
sudo luarocks install lua-zlib ZLIB_DIR=$(xcrun --show-sdk-path)/usr
2. 使用 lua-zlib 套件
先做個測試檔案,內容寫 abcdefg,再用 gzip 壓起來,
這會產生一個 aaa.gz 檔案:
echo abcdefg > aaa gzip aaa
來看看怎麼用 lua-zlib 解開這個 aaa.gz 的內容吧~
讀檔之後,可以看到檔案的內容是一串奇怪的資料,
這是被 gzip 壓縮過後的資料:
> f = io.open("aaa.gz", "r") > data = f:read() > data cAlaaaaKLJNIMK�$*S
接下來引用 zlib 模組,
接著用 zlib.inflate()
函式來解開資料。
這邊比較特別的是 zlib.inflate()
函式還可以傳參數進去 (也可以不傳),
這會傳回一個另一個函式,這個函式才是真正拿來解資料的。
解成功的話,第一個傳回值就是解完的資料,
可以看到它有成功解出原始值 abcdefg:
> zlib = require "zlib" > zlib.inflate()(data) abcdefg true 32 8
其他的用法就再請直接參考 lua-zlib 網站上面的說明囉~
參考資料:
Lua: How to gzip a string (gzip, not zlib) in memory? – Stack Overflow
Cannot find zlib headers on macOS 10.15 Catalina – Rob Allen’s DevNotes
homebrew – brew install zlib-devel on Mac OS X Mavericks – Stack Overflow