使用 HTTPie 進行 API 測試

2019-09-12 10:29:00

使用 HTTPie 偵錯 API,這是一個用 Python 寫的易用的命令列工具。

HTTPie 是一個非常易用、易於升級的 HTTP 用戶端。它的發音為 “aitch-tee-tee-pie” 並以 http 命令執行,它是一個用 Python 編寫的來用於存取 Web 的命令列工具。

由於這是一篇關於 HTTP 用戶端的指導文章,因此你需要一個 HTTP 伺服器來試用它。在這裡,存取 httpbin.org,它是一個簡單的開源 HTTP 請求和響應服務。httpbin.org 網站是一種測試 Web API 的強大方式,並能仔細管理並顯示請求和響應內容,不過現在讓我們專注於 HTTPie 的強大功能。

Wget 和 cURL 的替代品

你可能聽說過古老的 Wget 或稍微新一些的 cURL 工具,它們允許你從命令列存取 Web。它們是為存取網站而編寫的,而 HTTPie 則用於存取 Web API。

網站請求發生在計算機和正在閱讀並響應它所看到的內容的終端使用者之間,這並不太依賴於結構化的響應。但是,API 請求會在兩台計算機之間進行結構化呼叫,人並不是該流程內的一部分,像 HTTPie 這樣的命令列工具的引數可以有效地處理這個問題。

安裝 HTTPie

有幾種方法可以安裝 HTTPie。你可以通過包管理器安裝,無論你使用的是 brewaptyum 還是 dnf。但是,如果你已設定 virtualenvwrapper,那麼你可以用自己的方式安裝:

$ mkvirtualenv httpie...(httpie) $ pip install httpie...(httpie) $ deactivate$ alias http=~/.virtualenvs/httpie/bin/http$ http -b GET https://httpbin.org/get{    "args": {},    "headers": {        "Accept": "*/*",        "Accept-Encoding": "gzip, deflate",        "Host": "httpbin.org",        "User-Agent": "HTTPie/1.0.2"    },    "origin": "104.220.242.210, 104.220.242.210",    "url": "https://httpbin.org/get"}

通過將 http 別名指向為虛擬環境中的命令,即使虛擬環境在非活動狀態,你也可以執行它。你可以將 alias 命令放在 .bash_profile.bashrc 中,這樣你就可以使用以下命令升級 HTTPie:

$ ~/.virtualenvs/httpie/bin/pip install -U pip

使用 HTTPie 查詢網站

HTTPie 可以簡化查詢和測試 API。上面使用了一個選項,-b(即 --body)。沒有它,HTTPie 將預設列印整個響應,包括響應頭:

$ http GET https://httpbin.org/getHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Connection: keep-aliveContent-Encoding: gzipContent-Length: 177Content-Type: application/jsonDate: Fri, 09 Aug 2019 20:19:47 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block{    "args": {},    "headers": {        "Accept": "*/*",        "Accept-Encoding": "gzip, deflate",        "Host": "httpbin.org",        "User-Agent": "HTTPie/1.0.2"    },    "origin": "104.220.242.210, 104.220.242.210",    "url": "https://httpbin.org/get"}

這在偵錯 API 服務時非常重要,因為大量資訊在響應頭中傳送。例如,檢視傳送的 cookie 通常很重要。httpbin.org 提供了通過 URL 路徑設定 cookie(用於測試目的)的方式。以下設定一個標題為 opensource, 值為 awesome 的 cookie:

$ http GET https://httpbin.org/cookies/set/opensource/awesomeHTTP/1.1 302 FOUNDAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Connection: keep-aliveContent-Length: 223Content-Type: text/html; charset=utf-8Date: Fri, 09 Aug 2019 20:22:39 GMTLocation: /cookiesReferrer-Policy: no-referrer-when-downgradeServer: nginxSet-Cookie: opensource=awesome; Path=/X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>Redirecting...</title><h1>Redirecting...</h1><p>You should be redirected automatically to target URL:<a href="/cookies">/cookies</a>.  If not click the link.

注意 Set-Cookie: opensource=awesome; Path=/ 的響應頭。這表明你預期設定的 cookie 已正確設定,路徑為 /。另請注意,即使你得到了 302 重定向,http 也不會遵循它。如果你想要遵循重定向,則需要明確使用 --follow 標誌請求:

$ http --follow GET https://httpbin.org/cookies/set/opensource/awesomeHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Connection: keep-aliveContent-Encoding: gzipContent-Length: 66Content-Type: application/jsonDate: Sat, 10 Aug 2019 01:33:34 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block{    "cookies": {        "opensource": "awesome"    }}

但此時你無法看到原來的 Set-Cookie 頭。為了看到中間響應,你需要使用 --all

$ http --headers --all --follow GET https://httpbin.org/cookies/set/opensource/awesomeHTTP/1.1 302 FOUNDAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Content-Type: text/html; charset=utf-8Date: Sat, 10 Aug 2019 01:38:40 GMTLocation: /cookiesReferrer-Policy: no-referrer-when-downgradeServer: nginxSet-Cookie: opensource=awesome; Path=/X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockContent-Length: 223Connection: keep-aliveHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Content-Encoding: gzipContent-Type: application/jsonDate: Sat, 10 Aug 2019 01:38:41 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockContent-Length: 66Connection: keep-alive

列印響應體並不有趣,因為你大多數時候只關心 cookie。如果你想看到中間請求的響應頭,而不是最終請求中的響應體,你可以使用:

$ http --print hb --history-print h --all --follow GET https://httpbin.org/cookies/set/opensource/awesomeHTTP/1.1 302 FOUNDAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Content-Type: text/html; charset=utf-8Date: Sat, 10 Aug 2019 01:40:56 GMTLocation: /cookiesReferrer-Policy: no-referrer-when-downgradeServer: nginxSet-Cookie: opensource=awesome; Path=/X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockContent-Length: 223Connection: keep-aliveHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Content-Encoding: gzipContent-Type: application/jsonDate: Sat, 10 Aug 2019 01:40:56 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockContent-Length: 66Connection: keep-alive{  "cookies": {    "opensource": "awesome"  }}

你可以使用 --print 精確控制列印的內容(h:響應頭;b:響應體),並使用 --history-print 覆蓋中間請求的列印內容設定。

使用 HTTPie 下載二進位制檔案

有時響應體並不是文字形式,它需要傳送到可被不同應用開啟的檔案:

$ http GET https://httpbin.org/image/jpegHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Connection: keep-aliveContent-Length: 35588Content-Type: image/jpegDate: Fri, 09 Aug 2019 20:25:49 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block+-----------------------------------------+| NOTE: binary data not shown in terminal |+-----------------------------------------+

要得到正確的圖片,你需要儲存到檔案:

$ http --download GET https://httpbin.org/image/jpegHTTP/1.1 200 OKAccess-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: *Connection: keep-aliveContent-Length: 35588Content-Type: image/jpegDate: Fri, 09 Aug 2019 20:28:13 GMTReferrer-Policy: no-referrer-when-downgradeServer: nginxX-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockDownloading 34.75 kB to "jpeg.jpe"Done. 34.75 kB in 0.00068s (50.05 MB/s)

試一下!圖片很可愛。

使用 HTTPie 傳送自定義請求

你可以傳送指定的請求頭。這對於需要非標準頭的自定義 Web API 很有用:

$ http GET https://httpbin.org/headers X-Open-Source-Com:Awesome{  "headers": {    "Accept": "*/*",    "Accept-Encoding": "gzip, deflate",    "Host": "httpbin.org",    "User-Agent": "HTTPie/1.0.2",    "X-Open-Source-Com": "Awesome"  }}

最後,如果要傳送 JSON 欄位(儘管可以指定確切的內容),對於許多巢狀較少的輸入,你可以使用快捷方式:

$ http --body PUT https://httpbin.org/anything open-source=awesome author=moshez{  "args": {},  "data": "{\"open-source\": \"awesome\", \"author\": \"moshez\"}",  "files": {},  "form": {},  "headers": {    "Accept": "application/json, */*",    "Accept-Encoding": "gzip, deflate",    "Content-Length": "46",    "Content-Type": "application/json",    "Host": "httpbin.org",    "User-Agent": "HTTPie/1.0.2"  },  "json": {    "author": "moshez",    "open-source": "awesome"  },  "method": "PUT",  "origin": "73.162.254.113, 73.162.254.113",  "url": "https://httpbin.org/anything"}

下次在偵錯 Web API 時,無論是你自己的還是別人的,記得放下 cURL,試試 HTTPie 這個命令列工具。