å¦‚æžœä½ å†™è¿‡API,一定é‡åˆ°è¿‡è¿™æ ·çš„场景:åŒäº‹é—®ä½ æŸä¸ªæŽ¥å£æ€Žä¹ˆç”¨ï¼Œä½ 打开文档一看,å‘现文档和代ç 对ä¸ä¸Šã€‚æˆ–è€…æ›´æƒ¨ï¼Œä½ è‡ªå·±å†™çš„API,三个月åŽè‡ªå·±éƒ½å¿˜äº†å½“åˆä¸ºä»€ä¹ˆè¿™ä¹ˆè®¾è®¡ã€‚

RESTful䏿˜¯æ•™æ¡ï¼Œæ˜¯çº¦å®š
很多人把RESTful当æˆä¸€ç§å¿…é¡»ä¸¥æ ¼éµå®ˆçš„è§„èŒƒï¼Œå…¶å®žå®ƒæ›´åƒæ˜¯ä¸€ç§çº¦å®šä¿—æˆçš„æ²Ÿé€šæ–¹å¼ã€‚å°±åƒè‹±è¯æœ‰è¯æ³•,但日常对è¯ä¸å¤§å®¶éƒ½èƒ½ç†è§£ä¸€æ ·ï¼ŒRESTful的目的是让API更容易ç†è§£å’Œä½¿ç”¨ã€‚
æ ¸å¿ƒåŽŸåˆ™å¾ˆç®€å•:
- 用URL表示资æº
- 用HTTP方法表示æ“作
- 用状æ€ç 表示结果
URL设计:让资æºè‡ªå·±è¯´è¯
好的URL设计应该åƒè‡ªç„¶è¯è¨€ä¸€æ ·ç›´è§‚。æ¥çœ‹ä¸€ç»„对比:
糟糕的设计:
GET /getUserById?id=123
POST /createNewUser
POST /deleteUser?id=123
GET /getAllUsers
优雅的设计:
GET /users/123
POST /users
DELETE /users/123
GET /users
看出区别了å—?好的URL设计把动作交给了HTTP方法,URLæœ¬èº«åªæè¿°èµ„æºã€‚è¿™æ ·å³ä½¿ä¸çœ‹æ–‡æ¡£ï¼Œä½ 也能猜出这些接å£å¤§æ¦‚是干嘛的。
HTTP方法:ä¸åªæ˜¯GETå’ŒPOST
å¾ˆå¤šäººä¹ æƒ¯åªç”¨GETå’ŒPOST,但其实HTTPæä¾›äº†ä¸°å¯Œçš„è¯ä¹‰ï¼š
| 方法 | è¯ä¹‰ | å¹‚ç‰æ€§ |
|---|---|---|
| GET | 获å–èµ„æº | ✓ |
| POST | åˆ›å»ºèµ„æº | ✗ |
| PUT | 完整更新 | ✓ |
| PATCH | 部分更新 | ✗ |
| DELETE | åˆ é™¤èµ„æº | ✓ |
å¹‚ç‰æ€§æ˜¯ä¸ªé‡è¦æ¦‚念。幂ç‰çš„æ“ä½œæ‰§è¡Œå¤šæ¬¡å’Œæ‰§è¡Œä¸€æ¬¡æ•ˆæžœç›¸åŒã€‚比如DELETEåˆ é™¤ä¸€ä¸ªä¸å˜åœ¨çš„资æºï¼Œè¿”回404或204都å¯ä»¥ï¼Œä½†ç»“æžœæ˜¯ä¸€æ ·çš„ã€‚è€ŒPOSTåˆ›å»ºèµ„æºæ¯æ¬¡éƒ½ä¼šç”Ÿæˆæ–°çš„ï¼Œæ‰€ä»¥ä¸æ˜¯å¹‚ç‰çš„。
状æ€ç :别åªç”¨200å’Œ500
我è§è¿‡å¤ªå¤šAPIä¸ç®¡æˆåŠŸå¤±è´¥éƒ½è¿”å›ž200,然åŽåœ¨body里自己定义一套状æ€ç 。这完全是画蛇添足。HTTP状æ€ç å·²ç»æä¾›äº†ä¸°å¯Œçš„è¯ä¹‰ï¼š
- 200 OK – 请求æˆåŠŸ
- 201 Created – 资æºåˆ›å»ºæˆåŠŸ
- 204 No Content – æˆåŠŸä½†æ— è¿”å›žå†…å®¹ï¼ˆå¦‚DELETE)
- 400 Bad Request – è¯·æ±‚å‚æ•°é”™è¯¯
- 401 Unauthorized – 未认è¯
- 403 Forbidden – æ— æƒé™
- 404 Not Found – 资æºä¸å˜åœ¨
- 409 Conflict – 资æºå†²çªï¼ˆå¦‚é‡å¤åˆ›å»ºï¼‰
- 422 Unprocessable Entity – è¯ä¹‰é”™è¯¯ï¼ˆå¦‚é‚®ç®±æ ¼å¼ä¸å¯¹ï¼‰
- 429 Too Many Requests – 请求过于频ç¹
- 500 Internal Server Error – æœåŠ¡å™¨å†…éƒ¨é”™è¯¯
åˆç†ä½¿ç”¨çжæ€ç 能让客户端更容易处ç†é”™è¯¯ã€‚比如看到401就知é“è¦é‡æ–°ç™»å½•,看到429就知é“è¦é™æµã€‚
错误处ç†ï¼šç»™å¼€å‘者有用的信æ¯
错误å“应应该包å«è¶³å¤Ÿçš„ä¿¡æ¯å¸®åЩ开å‘者定ä½é—®é¢˜ã€‚一个好的错误å“åº”é•¿è¿™æ ·ï¼š
{
"error": {
"code": "INVALID_PARAMETER",
"message": "è¯·æ±‚å‚æ•°éªŒè¯å¤±è´¥",
"details": [
{
"field": "email",
"issue": "æ ¼å¼ä¸æ£ç¡®"
}
],
"requestId": "req_abc123xyz"
}
}
包å«é”™è¯¯ç ã€å¯è¯»çš„错误信æ¯ã€å…·ä½“细节ã€ä»¥åŠè¯·æ±‚ID(便于åŽç«¯æŽ’查日志)。这比一个简å•çš„{“error”: “bad request”}有用得多。
版本控制:API也会å˜è€
API䏿˜¯ä¸€æˆä¸å˜çš„。当需è¦ç ´åæ€§å˜æ›´æ—¶ï¼Œç‰ˆæœ¬æŽ§åˆ¶èƒ½æ•‘ä½ ä¸€å‘½ã€‚å¸¸è§çš„版本ç–略:
URL路径版本:
/v1/users
/v2/users
Header版本:
Accept: application/vnd.api+json;version=2
URL版本更直观,Header版本更优雅。选哪个å–å†³äºŽä½ çš„å›¢é˜Ÿåå¥½ï¼Œä½†ä¸€å®šè¦æœ‰ç‰ˆæœ¬ç–略。
分页:大数æ®çš„必修课
当列表数æ®å¯èƒ½å¾ˆå¤§æ—¶ï¼Œåˆ†é¡µæ˜¯å¿…须的。常è§çš„分页方å¼ï¼š
Offset分页:
GET /users?offset=20&limit=10
简å•直观,但深度分页性能差(OFFSET 1000000会很慢)。
Cursor分页:
GET /users?cursor=eyJpZCI6MTIzfQ==&limit=10
性能更好,适åˆå¤§æ•°æ®é‡ï¼Œä½†ä¸æ”¯æŒè·³é¡µã€‚
å“应ä¸åº”该包å«åˆ†é¡µå…ƒä¿¡æ¯ï¼š
{
"data": [...],
"pagination": {
"total": 1000,
"offset": 20,
"limit": 10,
"hasMore": true
}
}
写在最åŽ
好的API设计是一门艺术。它需è¦åœ¨ç®€æ´å’Œå®Œå¤‡ä¹‹é—´æ‰¾å¹³è¡¡ï¼Œåœ¨è§„èŒƒå’Œçµæ´»ä¹‹é—´åšå–èˆã€‚没有完美的APIï¼Œåªæœ‰ä¸æ–改进的API。
è®°ä½ï¼šAPI是写给其他开å‘者(包括未æ¥çš„自己)看的。多花10分钟设计,能çœä¸‹æœªæ¥å‡ å°æ—¶çš„调试时间。
最åŽï¼ŒæŽ¨èå‡ ä¸ªå¦ä¹ 资æºï¼š
- 《RESTful Web APIs》 – ç»å…¸æ•™æ
- GitHub REST API文档 – ä¸šç•Œæ ‡æ†
- Stripe API文档 – 文档å³äº§å“的典范
æ„¿ä½ çš„API优雅如诗,文档清晰如画。