開發與除錯
本頁彙整了撰寫外掛時有用的工具:開發者模式下的測試環境、瀏覽器套件的開發載入方式、日誌、檢查工具和一致性測試。
開發者模式
注意
在開發者模式之外,Nginx UI 只安裝已簽章的外掛套件。開發期間,請在測試環境(切勿在正式環境)上開啟 偏好設定 > 外掛 > 開發者模式。開發者模式會:
- 允許從上傳、命令列或離線外掛套件目錄安裝未簽章的外掛套件;
- 在 外掛 頁面顯示開發工具。
它永遠不會接受簽章已損壞的外掛套件,也不會讓未簽章的外掛參與自動更新。參見簽章與信任。
快速重新安裝
伺服器端進程的每次修改都需要一個新的外掛套件。有兩種方法可以縮短這個循環:
- 在伺服器上先執行
nginx-ui plugin pack <目錄> <外掛套件>,再執行nginx-ui plugin install <外掛套件> --enable --approve-permissions,一步取代已安裝的版本。 - 把外掛套件放進外掛目錄下的
packages目錄(預設是<設定目錄>/plugins/packages),Nginx UI 下次啟動時如果發現它的版本比已安裝的新,就會安裝它,然後把它移到packages/installed。
發行版也可以把外掛套件放在一個唯讀目錄裡,用 [plugin] 區段的 BundledDir 或環境變數 NGINX_UI_PLUGIN_BUNDLED_DIR 指定。官方 Docker 映像檔就是這樣內建 DNS-01 外掛的。Nginx UI 會把每個內建外掛安裝並啟用一次;內建的外掛套件版本更新時會升級它;使用者解除安裝後不會再自動裝回來。只有用官方外掛金鑰簽署的外掛套件會從這個目錄安裝。
開發瀏覽器套件
瀏覽器套件可以從本機開發伺服器載入,而不是從已安裝的外掛套件載入,這樣重新建置後只需重新整理頁面:
- 在執行瀏覽器的機器上用開發伺服器提供外掛目錄(包括
plugin.json),例如vite build --watch加一個靜態檔案伺服器。 - 在 外掛 頁面開啟分頁旁的選單,選擇開發外掛網址,輸入
plugin.json的網址,例如http://localhost:5173/plugin.json。 - 重新整理頁面。
Nginx UI 會相對於該網址載入清單中指定的瀏覽器套件、樣式表和頁面。由於頁面每次造訪都會執行這個指令碼,只接受 localhost 網址。清空網址即可回到已安裝的版本。
瀏覽器套件一頁介紹了如何建置瀏覽器套件。
日誌
注意
外掛把自己的日誌寫到標準錯誤。Nginx UI 會擷取這些輸出,並在 外掛 頁面的外掛詳細資料中顯示。標準輸出只能用於協定訊息,寫入任何其他內容都會破壞連線。SDK 會自動把日誌輸出到標準錯誤。
外掛還可以透過 host.log 方法傳送結構化日誌,參見宿主 API。絕不要記錄認證或權杖,參見權限與安全。
檢查外掛
靜態檢查
nginx-ui plugin lint <外掛目錄或外掛套件>檢查工具讀取外掛的清單和檔案,一次回報所有問題:清單欄位、外掛套件的結構與限制、簽章、能力區塊、範本和翻譯檔案。每個問題都有層級(error 或 warning)和規則名稱,檢查規則解釋了每一條規則。
有錯誤的外掛套件無法安裝。警告也應修正:它們指出的問題會被安裝外掛的人看到。
一致性測試
nginx-ui plugin conformance <外掛目錄或外掛套件> [參數]一致性測試使用 Nginx UI 自己的進程管理器和宿主 API 啟動外掛,檢查它的行為:交握、健康檢查、錯誤碼、並行呼叫、關閉,以及它宣告的每個能力的呼叫。測試絕不會呼叫會存取真實服務商或修改真實資料的方法:例如對 DNS-01 外掛只會要求它驗證一個空設定,而不會發佈記錄。
| 參數 | 意義 |
|---|---|
--capability | 只測試某一個能力,例如 dns01。 |
--transport | stdio、grpc 或 both。外掛提供 gRPC 時預設為 both,否則為 stdio。 |
--timeout | 整個測試的時間上限,預設為 90s。 |
提供 gRPC 的外掛會在兩種傳輸方式上分別測試,且結果必須一致。沒有伺服器端進程的外掛只進行靜態檢查。
協定範例
plugin-spec 儲存庫的 vectors/v1 目錄為每個方法提供了請求與回應範例。不使用 SDK 撰寫外掛時,可以在單元測試中使用它們。Go SDK 的 sdk.Run 和 Rust SDK 的 run 可以透過記憶體內的管道驅動外掛,用途相同。
常見問題
| 現象 | 原因 |
|---|---|
| 外掛啟動後立即失敗。 | 交握前向標準輸出寫入了內容,或缺少目前平台的可執行檔。請查看外掛日誌。 |
| 交握因能力不符而失敗。 | 進程回報的能力與清單中的 capabilities 不一致。 |
| 進程每隔幾秒就被重新啟動。 | 忙碌時沒有回應 plugin.ping。應獨立於耗時呼叫處理健康檢查,參見生命週期。 |
| 宿主呼叫回傳權限錯誤。 | 清單沒有請求該權限,或者使用者尚未核准。 |
| 瀏覽器套件沒有載入。 | 它沒有用清單 ID 呼叫 registerPlugin,或者打包了自己的 Vue。參見瀏覽器套件。 |