RESTful URL
URL 用名词、层级表达从属、查询参数表达过滤与分页、版本号放哪里。
Key PointsURL 只标识资源:路径用复数名词、层级表达从属,过滤/排序/分页一律走查询参数。
用名词,不用动词
The method already expresses the action, so a verb in the path is redundant. The test: read the URL aloud — it should name a thing, not an operation.
| Bad | Good |
|---|---|
| GET /getUsers | GET /users |
| POST /createUser | POST /users |
| POST /users/42/delete | DELETE /users/42 |
| GET /users/42/getOrders | GET /users/42/orders |
层级表达从属
Express ownership through nesting, but keep it at most two levels deep; anything deeper deserves its own top-level address.
Text
GET /users/42/orders 42 号用户的订单
GET /users/42/orders/7 42 号用户的 7 号订单
GET /orders/7 更好:订单本身有全局 id 时直接访问过滤、排序、分页走查询参数
These are view parameters over a collection, not new resources. Putting them in the path explodes the URL space and breaks caching.
Text
GET /orders?status=paid&minTotal=100
GET /orders?sort=-createdAt,total
GET /orders?page=3&size=20
GET /orders?cursor=eyJpZCI6OTAwMX0版本号放哪里
| Option | Example | Trade-off |
|---|---|---|
| Path | /v1/users | Simplest, easy to route and cache |
| Header | Accept: application/vnd.api.v2+json | Clean URLs, harder to test by hand |
| Query | /users?version=2 | Easy but pollutes caching keys |
Bump the version only for breaking changes; adding fields or optional parameters is not one. A published version must be maintained for a long time — avoid adding one unless you must.
命名规范清单
- 集合用复数:/users、/orders
- 一律小写,多个单词用连字符:/order-items
- 不要在 URL 里出现文件扩展名:用 Accept 协商
- 不要在 URL 里放自增 id 之外的含义,如 /users/me 只作为别名
- 结尾不加斜杠,全站统一
用名词,不用动词
方法已经表达了动作,路径里再写动词就是重复。判断标准:把 URL 念出来,应该是一个「东西」,而不是一个「操作」。
| 不推荐 | 推荐 |
|---|---|
| GET /getUsers | GET /users |
| POST /createUser | POST /users |
| POST /users/42/delete | DELETE /users/42 |
| GET /users/42/getOrders | GET /users/42/orders |
层级表达从属
从属关系用路径层级表达,但层级不要超过两层——再深就该直接给出子资源的顶层地址。
Text
GET /users/42/orders 42 号用户的订单
GET /users/42/orders/7 42 号用户的 7 号订单
GET /orders/7 更好:订单本身有全局 id 时直接访问过滤、排序、分页走查询参数
这些是「对集合的视图参数」,不是新的资源,放路径里会让 URL 爆炸且无法缓存。
Text
GET /orders?status=paid&minTotal=100
GET /orders?sort=-createdAt,total
GET /orders?page=3&size=20
GET /orders?cursor=eyJpZCI6OTAwMX0版本号放哪里
| 方案 | 例子 | 取舍 |
|---|---|---|
| 路径 | /v1/users | 最简单,路由与缓存都好处理 |
| 请求头 | Accept: application/vnd.api.v2+json | URL 干净,手工调试麻烦 |
| 查询参数 | /users?version=2 | 简单但污染缓存键 |
不兼容的破坏性变更才升版本;新增字段、新增可选参数不算。版本号一旦发布就要长期维护,能不加就不加。
命名规范清单
- 集合用复数:/users、/orders
- 一律小写,多个单词用连字符:/order-items
- 不要在 URL 里出现文件扩展名:用 Accept 协商
- 不要在 URL 里放自增 id 之外的含义,如 /users/me 只作为别名
- 结尾不加斜杠,全站统一