与普遍看法相反,REST 并不是真正的 URL 结构。事实上,应该只有一个“人类可读”的 URL,其余的都是由 HATEOAS 发现的。
此外,不应有任何“用于创建问题的 URL”。应该有一个(或多个)问题容器,当您在那里发布时,会创建新实体。同样,一旦你有了问题 URL(在创建时返回,客户端不应该知道它有什么“结构”),你可以在那里做新的 POST 来创建答案。
在您的示例中,一旦您执行任何所需的身份验证,对“根”URL 的 GET 可以返回包含所有所需容器的“主”资源:
GET /api/
=> { "questions":"/api/questions/", .... }
GET /api/questions/
=> [{"name":"firstone", "href":"/api/questions/11"},
{"name":"final", "href":"/api/questions/43"}]
GET /api/questions/101
=> {
"name":"firstone",
"href":"/api/questions/11",
"text":"2+2",
"answers":[
{"key":"A", "text":"23", "href":"/api/answers/15"},
{"key":"B", "text":"3", "href":"/api/answers/34"},
{"key":"C", "text":"4", "href":"/api/answers/7"}
]
}
添加一个新问题:
POST /api/questions/ {"name":"onemore", "text":"2^2"}
=> 201 Location: /api/questions/45
data: {"name":"onemore", "text":"2^2", "href":"/api/questions/45"}
GET /api/questions/45
=> {"name":"onemore", "text":"2^2", "href":"/api/questions/45"}
添加答案:
POST /api/questions/45 {"key":"A", "text":"4.5"}
=> 201 Location: /api/answers/56
data: {"key":"A", "text":"4.5", "href":"/api/answers/56", "question":"/api/questions/45"}
修改答案文本:
PUT /api/answers/56 {"key":"A", "text":"4.8"}
=> 200
data: {"key":"A", "text":"4.5", "href":"/api/answers/56", "question":"/api/questions/45"}
当然,这有很多变体,尤其是当您 GET 容器时返回了多少“深度”信息。在这个例子中,当你得到一个问题时,会有一个答案列表。在一个极端,它可能只是一个 URL 列表,客户端必须获取每个 URL,在另一个极端,它可能是每个 URL 的全部数据,因此您只需一个请求即可获得所需的一切。
通常,您必须为每个容器选择一个平衡点,可能有一些“基本”字段可以从第一个请求中获得,而其他字段可能会延迟。