URL、正文或标头中的 RESTful API 子类型?

Posted

技术标签:

【中文标题】URL、正文或标头中的 RESTful API 子类型?【英文标题】:RESTful API subtype in URL, body or header? 【发布时间】:2014-02-14 10:18:09 【问题描述】:

我对哪种 RESTful 设计更好感到有些困惑。

对于 API,我有三种类型; QuestionAnswerStudentQuestion 类型有两个子类型; MultipleChoiceOpenQuestion 类型将来可能会有更多的子类型。请注意,子类型具有共同和不同(可选)的属性。 Answer 适用于所有问题。

我见过类似的问题(Modeling Object Inheritance in a REST Api、How to model a RESTful API with inheritance?),给出的答案指向使用通用 URL 并在正文中指定类型。但是我不觉得答案是权威的(没有参考最佳实践,没有很多支持等)。

我正在寻找基于事实而非观点的权威、可信的答案。

我将在下面解释可能的设计。

输入网址

可以使用GET /questions 请求所有问题的列表。这将返回一个包含问题摘要的 JSON 列表:

[
  
    "url": "http://example.com/questions/multiplechoice/1",
    "name": "example question"
  ,
  
    "url": "http://example.com/questions/open/2",
    "name": "another question"
  
]

可以使用GET /questions/multiplechoice 请求选择题列表。

可以使用POST /questions/multiplechoice创建一个新的多项选择题

服务器端这些 URL 映射到不同的请求处理程序。这样做的好处是无需检查来检查要创建/返回的类型,它隐含在 URL 中。

这种方法的缺点(我认为)是,当学生提交答案时,问题的 URL 会有所不同。 POST /questions/multiplechoice/1/answersPOST /questions/open/2/answers

输入正文

请求所有问题的列表保持不变,GET /question。输出也是一样的。

请求选择题列表意味着过滤,所以这将是GET /questions?type=multiplechoice

创建一个新的多项选择题意味着还要发布类型。 POST 数据为:


  "type": "multiplechoice",
  "name": "example question"

这样做的好处是 URL 保持简单并且将来不太可能更改。缺点是一个请求处理程序需要将基于主体的请求分派(使用某种映射)到特定于该类型的其他处理程序。

使用通用 URL 提交答案:POST /questions/:question_id/answers

输入标题

可以使用Content-TypeAccept 标头代替type 参数。

要获取所有问题的列表:GET /questions

要获得所有多项选择题的列表:GET /questionsAccept 设置为 application/app.multiplechoice+json

这种方法类似于输入法。额外的缺点是这涉及自定义 mime 类型,如果您问我,这并不是很明显。

【问题讨论】:

不幸的是,正如 Andres 所说,API 设计非常主观。举一些很好的例子,但也许您可以提供更多信息,例如,您是否需要一次提交多个不同类型的问题?此外,您是否需要整理所有学生对一个问题的答案?这会影响答案是问题的子资源还是完全不同的仅具有问题链接的东西。 @James 问题不是批量创建的。我不认为这会严重影响 API 设计。通常通过问题访问答案,这遵循域设计(没有问题就不可能存在答案)。无论 API 设计的主观性如何,都必须有针对此类“通用”问题的解决方案。 (在软件架构中有设计模式,这些是主观的,但如果应用得当,可以为项目提供坚实的基础。) 我完全同意,并且有一些关于这个主题的好书和文章,但就像其他设计模式一样,选择正确的设计模式是困难的(和主观的)部分。不过,您要解决的问题很常见;我将其称为具有同一资源的多种表示形式;此外,可能值得忘记继承/对象模型并更多地考虑这些资源的行为,如果它们稍后碰巧映射到分层对象模型,那只是一个 impl 细节。我不认为我可以给出您正在寻找的答案;祝你好运! 【参考方案1】:

MultipleChoice 和 Open 是 Question 的子类型。所以,应该有包含 /question/multiplechoice 和 /question/open 的 url。

关于您不希望收到基于意见的答案,REST 不是 JEE 那样的标准,也不是 Spring 那样的实现。这是一种风格,如巴洛克式或哥特式。所以,你只会得到意见作为答案。

【讨论】:

正如问题所述,“我正在寻找基于事实而非观点的权威、可信的答案。” 这并不意味着没有经过验证的实现。另外,请在 cmets 部分进行 cmets。【参考方案2】:

根据他们给出的Rest Api best Practice 是最佳实践。在此 根据我们应该使用动词的标准,其余部分是基于资源的,所以我认为根据上面的 url,您的答案大部分相同。

For Get
    E.g:- Get/questions/multiplechoice  //// this case controller/action/id id(optional)
                                             this route config will resolve this route
          Get/questions/open          
For post
    E.g:- Post/questions/multiplechoice //// you can use same route for post/put/delete.

          Post/questions/open          

【讨论】:

以上是关于URL、正文或标头中的 RESTful API 子类型?的主要内容,如果未能解决你的问题,请参考以下文章

我应该通过 HTTP 标头或将正文作为 JSON 传递到 REST Api 吗?

RESTful API 中的 API 密钥加密?

RESTful API - 设计子资源

Angularjs调用restful api(post)没有成功错误请求

通过 RESTful API 中的 ID 或 slug 识别项目

视频你们的项目RESTful API设计规范是怎样的?