昨天,我們從 Google 登入一路看到 JWT、Cookie 和 CORS,也反覆碰到一件事:
Frontend 和 Backend 之間,每一次資料往來,都不是直接「把資料丟過去」而已。
中間會出現 Request、Response、Header、Body、Status Code……
前幾天,我們已經在不同情境裡,一個一個遇過這些名詞。
今天就把鏡頭拉遠一點,正式把它們放回同一張地圖裡。
我們平常很常說:
「打 API」。
但這句話背後,到底發生了什麼?
API 是什麼?Frontend 和 Backend 又是怎麼透過 HTTP,一來一回完成一次溝通的?
API,全名是 Application Programming Interface(應用程式介面)。
它是一套讓不同程式知道「可以怎麼跟彼此溝通」的規則。
而我們今天討論的,就是透過 Web 技術提供的 Web API。
如果把這件事放進 BuJo,再把它想成一間甜點店:
客人
↓
前台
↓
後場廚房
客人不會直接衝進廚房翻冰箱、拿材料。
他會透過前台點餐,再由前台把需求交給後場處理。
放回 BuJo:
Frontend
│
│ 透過 Web API
▼
Backend
例如使用者打開活動頁,Frontend 需要活動資料。
它不會直接跑進 Database 把資料撈出來,而是透過 API 向 Backend 提出要求:
「請給我這個活動的資料。」
Backend 收到後,再處理邏輯、查詢資料,最後把結果回給 Frontend。
那麼,Frontend 的這句「請給我活動資料」,到底是怎麼送到 Backend 的呢?
這時就會進到下一層:
HTTP。
HTTP,全名是 Hypertext Transfer Protocol(超文字傳輸協定)。
在我們現在討論的 Web API 裡,可以先把它理解成:
Client(用戶端) 和 Server(伺服器) 傳送訊息時共同遵守的一套通訊規則。
而最基本的一次 HTTP 溝通,可以拆成兩邊:
Client / Frontend
│
│ HTTP Request(請求)
▼
Server / Backend
│
│ HTTP Response(回應)
▼
Client / Frontend
也就是:
Request + Response。
而昨天講到的:
Response Header
Response Body
其實就是這張圖裡 HTTP Response 裡面的兩個部分。
今天我們只是把它們放回完整的 HTTP 溝通流程裡來看。
一次 HTTP Request 裡,其實會帶著好幾種不同資訊。
先把整張地圖攤開來看:
HTTP Request
│
├─ Method
│ → 想做什麼?
│
├─ Path
│ → 要操作哪個位置/資源?
│
├─ Parameter
│ ├─ Path Parameter
│ └─ Query Parameter
│
├─ Header
│ → 補充這次 Request 的相關資訊
│
└─ Body
→ 這次 Request 要傳送的主要資料內容
接下來,就照著這張圖,一個一個拆開來看。
假設我想取得某一個活動:
GET /api/activities/123
第一個可以先看的是 HTTP Method(HTTP 方法)。
常見的有:
| Method | 常見用途 |
|---|---|
GET |
取得資料 |
POST |
提交資料,常用來建立新資料 |
PUT |
取代指定資源的完整內容 |
PATCH |
修改資源的部分內容 |
DELETE |
刪除資料 |
例如:
GET /activities
→ 我想取得活動
POST /activities
→ 我要提交資料建立活動
PATCH /activities/123
→ 我要修改活動 123
DELETE /activities/123
→ 我要刪除活動 123
這裡也很常一起看到另一組縮寫:
CRUD。
Create → 建立
Read → 讀取
Update → 更新
Delete → 刪除
所以初學時可以先用:
POST ↔ Create
GET ↔ Read
PATCH ↔ Update
DELETE ↔ Delete
幫忙理解。
不過兩者不是完全一一對應的規則。
CRUD 描述的是資料操作的四種基本類型;HTTP Method 則有各自正式的 HTTP 語意,例如 POST 也不只可能拿來「建立資料」。
所以它比較像一張很好用的對照表,不是等號。
接下來是 Path(路徑)。
例如:
/api/activities
表示這一段 API 跟 Activities 有關。
如果是:
/api/activities/123
則進一步指向特定的一個活動。
實務上,我們也很常把一個可以被呼叫的 API 入口稱為:
Endpoint(API 端點)。
而一個 Endpoint 在辨識時,不能只看 Path。
例如:
GET /api/activities
和:
POST /api/activities
Path 一模一樣,但 Method 不同,代表的操作就完全不同。
所以看 API 時,通常會把:
Method + Path 一起看。
Request 裡也常會出現 Parameter(參數)。
其中最常看到兩種。
例如 Backend Route 寫成:
/api/activities/:id
其中:
:id
就是一個 Path Parameter。
真正呼叫時可能變成:
/api/activities/123
這裡的 123 就是這次真正要找的 Activity ID。
另一種則是接在網址後面的:
?status=recruiting
例如概念上:
/api/activities?status=recruiting
它比較像是在說:
活動我都知道去哪裡找了,但這次我還想多加一個查詢條件。
所以兩者可以先粗略地分:
Path Parameter
→ 用來指出這次操作的是哪個資源
Query Parameter
→ 再補充查詢、篩選、排序等條件
再往下一格,就是 Header(標頭)。
Header 用來補充這次 Request 的相關資訊,例如:
Content-Type
→ 送出的資料是什麼格式
Accept
→ 希望收到什麼格式的 Response
Authorization
→ 身分驗證/授權相關資訊
Cookie
→ 瀏覽器可能會一起帶上的 Cookie
像昨天看到的登入 Cookie,就是這一層會碰到的東西。
接下來再看 Request 裡承載主要資料的地方:
Body。
有些 Request 還會帶 Request Body(請求內容)。
例如建立活動時,Frontend 可能需要送:
{
"title": "週末下午茶",
"location": "台北"
}
像這種建立活動時要提交的主要資料,就會放在 Request Body。
Web API 很常用 JSON(JavaScript Object Notation) 交換這類結構化資料。
重點是:
一個 Request,遠遠不只是「打一個網址」。
Backend 收到 Request、處理完成之後,會回一個 HTTP Response(HTTP 回應)。
最常先看的有三塊:
HTTP Response
│
├─ Status Code
│ 狀態碼
│
├─ Header
│ 標頭
│
└─ Body
回應內容
Body 就是昨天拿來裝 JWT、User Data 的那個 Response Body。
而另一個我們超常看到的,就是:
HTTP Status Code(HTTP 狀態碼)。
Backend 處理完 Request 之後,會透過 HTTP Status Code(HTTP 狀態碼) 表示這次結果屬於哪一類。
HTTP 狀態碼可以分成五大類:
| 類別 | 大致代表 |
|---|---|
1xx |
資訊性回應 |
2xx |
成功 |
3xx |
重新導向 |
4xx |
Client Error |
5xx |
Server Error |
平常常看到的:
200
201
400
401
403
404
500
其實都屬於這套分類。
Status Code 就是 HTTP Response 用來表示這次 Request 結果類型的訊號。
至於 400、404、409 怎麼選,以及 Error 怎麼變成 500 Response,留到 Day21 再拆。
知道 Path 和 Method 之後,還有一個很常一起出現的概念:
REST API。
REST 會先把系統裡要操作的東西視為 Resource(資源),再透過 Path 和 Method 表達要對它做什麼。
也就是:
Method(要做什麼)+ Path(要找哪個 Resource)
=「要對哪個東西做什麼」
例如 BuJo 裡有:
activities
users
notifications
這些都可以被看成不同的 Resource(資源)。
接著再用 Path 指向要處理的 Resource,用 Method 表達要進行的操作:
GET /activities
→ 取得 Activities
POST /activities
→ 建立 Activity
GET /activities/123
→ 取得 Activity 123
PATCH /activities/123
→ 修改 Activity 123
所以 REST API 不是 Method 本身。
Method 只是其中一個組成元素。
REST API 真正在做的,是讓這些元素用比較一致、有規律的方式組合起來,讓人一看就知道:
「我要對哪個東西做什麼?」
REST 本身還有更完整的架構原則,但 Day19 先理解這一層就夠了。
最後,就用 BuJo 裡真的存在的一支 API,把今天講過的內容完整複習一次吧!
BuJo Backend 有一支:
GET /api/activities/:id
用途是:
取得某一個活動的詳細資料。
把今天學的東西一個一個套進去:
GET
→ HTTP Method
→ 我要取得資料
/api/activities/:id
→ Path
→ 指向 Activities 裡的某一個 Activity
:id
→ Path Parameter
→ 這次是哪一個 Activity?
成功:
200
→ Response Body 回傳 Activity
找不到:
404
→ 回傳 Error Response
實際 Backend Route 收到 Request 後,還會經過登入驗證,再交給對應的 Controller 處理。
所以整條路其實是:
Frontend
↓
GET /api/activities/:id
↓
HTTP Request
↓
BuJo Backend Route
↓
Controller
↓
取得/處理 Activity
↓
HTTP Response
↓
200 + Activity
或
404 + Error Response
↓
Frontend
複習到這裡,今天看到的 Method、Path、Parameter、Status Code、Request 和 Response,也就全部串進同一條流程裡了。
其實它們都在一起描述同一件事:
Frontend 要怎麼提出需求,Backend 又要怎麼把結果回傳回來。
而當一支 API 裡開始有這麼多規則,下一步就需要把它們整理成一套大家都能共同遵守的標準。
下一篇,就來看:
API Contract(API 契約)。