RESTful API 进阶

HATEOAS、缓存与 ETag、版本演进、以及与 GraphQL / gRPC 的取舍。

Advanced
Key Points进阶不是把 REST 做得更纯,而是在缓存、演进和协议选择上做对取舍。

HATEOAS

Responses carry links describing what can be done next, so clients navigate without hard-coded URLs. Worth it for public APIs whose capabilities change.

JSON
{
  "id": 42, "status": "pending",
  "_links": {
    "self":    {"href": "/orders/42"},
    "pay":     {"href": "/orders/42/payment", "method": "POST"},
    "cancel":  {"href": "/orders/42/cancel",  "method": "POST"}
  }
}

缓存与 ETag

Text
GET /users/42
→ 200 OK
  ETag: "a1b2c3"
  Cache-Control: private, max-age=60

GET /users/42
If-None-Match: "a1b2c3"
→ 304 Not Modified        (不传 body,省带宽)
  • Cache-Control: public 只给不因用户而异的资源
  • 带用户信息的响应一律 private,否则会被 CDN 缓存串号
  • 写操作后要能主动失效缓存(版本号或 purge)

版本演进

ChangeBreaking?How
Add a fieldNoJust ship it
Add an optional parameterNoDefault keeps old behaviour
Rename a fieldYesKeep both for one release
Change a typeYesNew version or new field
Remove an endpointYesDeprecate → 410 → remove

REST vs GraphQL vs gRPC

RESTGraphQLgRPC
TransportHTTP/1.1 + JSONHTTP POST + JSONHTTP/2 + protobuf
FetchingFixed per endpointClient picks fieldsFixed per method
CachingNative HTTP cacheHard, usually POSTCustom
Best forPublic APIs, CRUDComplex UIs, mobileInternal microservices
Do not swap internal CRUD for GraphQL because it sounds modern. The test: do clients really need to pick fields across many endpoints, and are round trips the bottleneck?

继续阅读

  • Swagger / OpenAPI —— 把上面这些约定写成机器可读的文档
  • HTTP 状态码 —— 逐个状态码的精确语义
  • OAuth 2.0 —— 授权码、客户端凭证与 token 生命周期

Friends & Partners