大多數開發者可能都用過 Postman,根據其官網的介紹:Postman 是一個用於構建和使用 API 的 API 平臺,簡化了 API 生命週期的每個步驟,提供更便捷的團隊共同作業,因此可以更快地建立更好的 API。這裡的 API,除了我們常用的 HTTP API 之外,還包括 Websocket(BETA),gRPC。本文中,我們將以最常用的 REST API 作為例子。
假設我們在開發一個類似微博的專案,你是一個後端開發人員,前端分為手機端和網頁端,而由於採用了 RAD 或者敏捷開發方法,你隨時需要將在開發環境測試好的最新的 API 改動釋出至測試環境(或 Stage 環境),併為測試人員或者前端開發人員提供最新的 API 檔案。下面我們看看在這個過程中,Postman 能如何幫助簡化 API 宣告週期以及提供更便捷的團隊共同作業。
在這個階段,不管後端使用什麼語言開發,最終開放的是 REST API 介面,在本文的範例中,我們使用 Jmix 框架開發基於服務的 REST API。Postman 的最基本用法,就是開發人員可以在這一步建立一個 API 集合(Collection),其中包含專案的所有 API,這裡我們建立了一個叫 Corp
的集合,包含所有功能的 API:
圖中重要的三個部分:
到這一步為止,就是 Postman 的基礎用法了,我們建立一個 API 集合,而集合是支援匯出的,可以匯出為 JSON 檔案,再發給其他同事,他們可以匯入到 Postman 裡面使用。
在上面的圖中,我們展示了集合中的第一個介面 - 獲取 Jmix 本地 token。而這個 token,我們需要在以後的每個請求中都用來做使用者認證。如下圖:
這裡有一個問題,就是 token 會過期,比如我們今天拿到的 token,可能明天就沒法再次使用了。而我們需要再次獲取 token,然後挨個複製到每個請求中嗎?這個未免太麻煩了。Postman 提供了環境變數的機制。有三種型別的變數,分別是:
Variables
分頁,可以定義集合級別的變數,這些變數,只能用於集合內的 API。我們可以宣告一個名為 jmixToken
的集合變數儲存 token,至然後在請求中使用 {{jmixToken}}
的方式參照變數即可:
除了 token 之外,我們在 API 中使用的相同型別的引數也都可以宣告為變數,而變數可以用在請求的任何部分。例如,我們在發新帖的 API 中使用的請求體如下,我們分別使用了 Postman 提供的隨機生成 UUID 的 $guid
變數、集合中儲存測試使用者 Id 的 userId
變數,以及儲存我們部落格地址 https://blog.abmcode.com
的 blogUrl
:
{
"postId":"{{$guid}}",
"userId":"{{userId}}",
"content":"歡迎存取:{{blogUrl}}"
}
經過了上面的第一輪優化後,我們的 API 裡面會多了許多變數。但是還存在一個問題,就是我們在拿到 token 後,仍然需要手動更新一下 jmixToken
這個變數,否則各個 API 仍然使用的是過期的 token。這還是有點麻煩。
好在 Postman 提供了測試指令碼的功能,可以解決這個小麻煩,我們需要在獲取 token 的請求中編寫一個測試指令碼,用於更新 jmixToken
,這樣我們一旦重新獲取了 token,就可以保證其他 API 使用的是最新的 token。
編寫程式碼的位置如下圖所示,在 API 的 Tests
分頁。並且更貼心的是,Postman 在右側給了一些常用的程式碼片段,點選即可使用,例如,獲取全域性變數、設定集合變數等。
測試指令碼是 JavaScript 的,可能需要有一點 JS 基礎,具體每行的作用,請參考註釋。這裡我們對返回結果做了兩個測試,分別是驗證 HTTP 狀態碼必須是 200 以及檢測返回結果中必須包含 access_token
這個屬性。需要注意的是,這兩個測試如果有任意一個失敗,都將丟擲異常直接退出 JS 的執行,此時不會走最後一句設定變數的語句:
// pm.test 表示這是一個測試。
pm.test("Set Global variable jmixToken", function () {
// 測試 1 - 返回狀態碼為 200
pm.response.to.have.status(200);
// 獲取返回結果的 json
var jsonData = pm.response.json();
// 測試 2 - 返回的 json 中必須有 access_token 欄位
pm.expect(jsonData).to.have.property('access_token');
// 設定全域性變數 jmixToken
pm.globals.set("jmixToken", jsonData.access_token);
})
這裡我們還可以做一點優化,那就是針對上面程式碼中的 「測試 1」,我們檢查了 HTTP 的返回狀態碼為 200,其實針對所有的請求,我們可能都需要做這個檢查,那麼如果不復制貼上程式碼,有沒有簡化的方法呢?
有的,Postman 提供了集合級別的測試指令碼,定義在集合中的測試指令碼,會對每個 API 都適用。比如,我們可以把驗證 HTTP 狀態碼的測試放到集合中:
到這裡,我們開發階段對於請求的優化就結束了,通過使用變數,可以優化 API 中的資料,將相同的資料都定義在變數中。通過測試指令碼,我們可以對 API 進行測試,也可以更新各種變數,避免手動修改的麻煩。我們的範例中演示的更新 token 是最常見的指令碼功能,除此之外,比方說我們要測試的發帖和回帖功能,可以在發帖後將貼文的 ID 儲存在變數中,測試回帖功能時,直接使用變數儲存的貼文 ID,這些具體的業務場景,可以根據專案靈活變化。
開發完成後,我們就需要將 API 部署至測試或者 Stage 環境,交給測試人員或者前端開發人員進行試整合了。那麼在這個階段,你或許想在測試人員工作前自己先測試一遍,或者如果測試有問題,而你作為後臺開發人員,也難免需要直接呼叫測試環境的 API 觀察輸出結果。這就有了一個新的問題:我們在之前的介面定義都是 http://localhost:8080
開頭的地址,怎麼能方便地切換到測試地址呢?
答案還是用變數。但是這一次,我們使用的是環境變數集合。
例如,我們可以建立兩套環境變數,分別為 env_dev
和 env_prod
,其中都定義了變數 jmixAppUrl
,在 env_dev
中,該變數的值為 http://localhost:8080
,而在 env_prod
中,該變數的值為 https://your.test.env.ip:test_port
,然後修改每個請求,將原本的 http://localhost:8080
地址換成變數 {{jmixAppUrl}}
:
使用時,通過右上角的環境變數集合切換功能,就可以切換不同的環境了。
如果你的測試或者前端也使用 Postman,那麼可能匯出 API 集合檔案再交由同事匯入,可能是比較方便的方法。但其實 Postman 在檔案釋出這個功能上,也做了不少工作。
右鍵點選集合,有一個 View documentation
選單,或者通過下圖的按鈕也可以檢視集合的檔案
在檢視檔案時,右上角有一個 Publish
按鈕,可以將你的檔案公開發布,並提供一個 URL 地址用於存取。這樣的話,其他同事如果不使用 Postman,只需要存取該地址,就可以看到 API 的檔案。
在釋出時,可以選擇環境變數集合,這樣會用集合內的變數值直接替換 API 中的所有變數,這樣一來,看檔案的人不會讀到看不懂的變數。下圖是一個釋出的檔案範例,前端使用者還可以根據程式語言,選擇對應的程式碼樣例:
釋出後的檔案會實時更新,也就是說,任何你在 Postman 中對集合 API 的修改都會實時同步至檔案中。比如新增或刪除某個 API、修改 API 請求體等等。
其實,我們最後還做了一個專案級別的優化,這個案例可能不具有通用性,但是也可以給大家一個思路:
由於我們的專案後臺都是基於 Jmix/CUBA 框架開發的,因此,我們做了如下改動:
jmixToken
,cubaToken
,ssoToken
。並且在上述三個介面的測試指令碼中,分別更新這三個全域性變數。這樣做的好處是,不需要在每個專案中單獨提供獲取 token 的 API,並能保證獲取的 token 全域性可用。
在業務 API 集合中,我們為 Collection 新增了 Pre-request Script
,這個指令碼會在集合內的每個請求發出前先執行。我們就是用這個指令碼為請求新增請求頭,程式碼很簡單,例如,對於使用 ssoToken
和 jmixToken
的 Jmix 專案,我們是這樣做的:
因此,對於集合內的每個請求,不需要單獨設定 Authorization 請求頭了。
最後,我們在程式碼層面對每個業務 API 的返回結構做了統一,都使用這樣的返回結構:
public class RestResult<T extends Serializable> implements Serializable {
/**
* 業務狀態碼
*/
private int businessCode;
/**
* 提示資訊
*/
private String msg;
/**
* 資料
*/
private T data;
//...
}
我們為所有的成功返回都定義了同一個 businessCode
,這樣的話,在 Postman 的 Tests 指令碼中,可以新增程式碼直接檢查業務層面的返回結果是否成功,例如,我們定義 10000 為業務結果正確的返回值:
pm.test("Success return", function () {
pm.response.to.have.status(200);
pm.expect(pm.response.json().businessCode).to.eql(10000);
})
本文介紹了一些使用免費 Postman 的進階技巧:變數、指令碼、檔案釋出。而現在 Postman 也在往 SaaS 方向發展,推出了團隊共同作業功能,像檔案釋出、API 匯出匯入這些功能在團隊模式下用不到了,因為 API 集合可以共同作業完成,檔案也可以團隊內共用。Postman 作為一款 API 平臺,確實能在一定程度上提升團隊的開發效率和共同作業。