與普遍的看法相反,REST並不是真的關於URL結構。事實上,應該只有一個'人類可讀的'URL,其餘的都是HATEOAS發現的。
此外,不應該有任何「創建問題的URL」。應該有一個(或許多)問題容器,當你在那裏發佈時,會創建新的實體。同樣,一旦你有了問題URL(創建時返回,客戶端不應該知道它具有什麼'結構'),你在那裏做新的POST來創建答案。
在你的榜樣,一旦你做任何所需autentication,一個GET的「根」 URL可以返回一個「主」資源提供一切必要的容器:
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"}
當然,這裏有很多變化,特別是當您獲取容器時會返回多少'深'信息。在這個例子中,當你得到一個問題時,有一個答案列表。一方面,它可能只是一個URL列表,客戶端必須獲取每一個URL,另一方面,它可能是每個URL的全部數據,因此您可以通過一個請求獲得所需的一切。
通常情況下,您必須爲每個容器選擇一個餘額,可能會有一些「基本」字段在第一次請求時很有用,而其他字段可能會延遲。
感謝您使用HTTP動詞的提示。所以你建議我POST到/ questions/{questionId}來創建一個問題的答案?這對我來說似乎不是很有表現力,但也許我錯過了REST的意義?這會比使用PUT來更新問題和回答更好嗎? **我在更新答案之前發佈了此信息,請讓我閱讀並查看它是否回答了我的問題 – benjyblack
太好了,謝謝您的詳細介紹。我仍然不完全相信POST/api/questions/45是創建答案的非常富有表現力的方式。例如,如果在一個問題上可以創建多個子實體? – benjyblack
不要在URL上考慮太多,請考慮資源。一些資源是容器,爲了創建一個新的資源,你POST到一個容器,服務器響應新的URL。將您輸入的現有資源更新爲其URL。如果一個問題可以有多種相關的實體,也許它不應該是一個容器本身,但是當你獲取它時,你會找到容器的URL。類似於'GET/api/questions/101 => {....,「answers」:「/ api/questions/101/answers /」,「hints」:「/ api/questions/101/hints /」, ....}'那麼你可以發佈到'answers'容器來添加一個新的。 – Javier