具有不同请求集的REST API POST / PUT

时间:2018-12-13 08:39:16

标签: rest api-design

创建或修改资源的post或put方法可以接受不同的请求对象集吗?

例如:我有一个名为'server'的资源。它可以通过os来区分。例如,我可以有两个资源实例-windows serverlinux server。 我在这里的基本决定是将它们视为相同类型的资源,即server

现在可能会发生,创建Windows服务器时,我的POST API会接受与同一API用于Linux服务器的请求对象不同的请求对象。

对于创建Windows服务器,我有-

POST : /v1/server
accepts 
{
    name : win-server-1
    os : 'windows'
    ms-office: 'Office2009'
}

对于创建linux服务器,我使用相同的api,但是使用了不同的请求对象-

POST : /v1/server
accepts
{
   name : linux-server-1,
   os : 'linux'
   kernel-version : '3.10.0' 
}

您可以看到Windows和Linux服务器的相同POST API接受的请求不同。我的业务逻辑将基于'os'属性处理这些请求。因此,从技术上讲,它将起作用(使用难看的开关盒)。 但这真的令人放松吗?还是我应该使用不同的API,例如/v1/windows-server/v1/linux-server,并为每个API定义唯一的请求定义?

3 个答案:

答案 0 :(得分:2)

从客户端的POV最好有一个端点。请注意,拥有单独的资源会将“丑陋切换”的必要性转移到客户端。

我会采用您当前的解决方案。客户的便利性和API的清晰性/简洁性比开发人员的更为重要。 API比实现更重要。恕我直言,您当前的解决方案在这方面更好:

  • 创建:POST /v1/servers
  • 获取:GET /v1/servers/{server_id} POST /v1/servers/{server_name}(给定名称是唯一的)返回单个资源
  • 查询:GET /v1/servers/?{filter_expression}(例如GET /v1/servers/?os=linux)返回(过滤后的)资源的集合(最好是分页)

我要更改的一件事是,将特定于操作系统的内容提取到嵌套资源中。这将使实现更加简单,API更加清晰:

{
    name : win-server-1,
    os : 'windows',
    config: {
        ms-office: 'Office2009'
    }
}

{
    name : linux-server-1,
    os : 'linux',
    config: {
        kernel-version : '3.10.0' 
    }
}

答案 1 :(得分:1)

  

但这真的很放松吗?

测试该问题的一种好方法是,询问您要做什么与网络相匹配。

在这种情况下,类似物将具有两种不同的形式,这些形式将请求提交给表单动作属性所描述的相同目标URI。

windows: <form action="/v1/server" method="post">
    <!-- ... -->
    Office: <input type="text" name="config.office"><br>
    <input type="submit" value="Submit">
</form> 

linux: <form action="/v1/server" method="post">
    <!-- ... -->
    Kernel-version: <input type="text" name="config.kernel-version"><br>
    <input type="submit" value="Submit">
</form>

任何符合标准的Web客户端都可以很好地处理。 text/html媒体类型的处理规则告诉客户端如何从这些形式中的每一个构造请求。

请注意,由于浏览器仅在处理form.action,因此可以轻松更改资源标识符。因此,如果您以后决定Windows和Linux请求应使用不同的请求,则可以轻松完成此操作:

windows: <form action="/v1/windows-server" method="post">
    <!-- ... -->
    Office: <input type="text" name="config.office"><br>
    <input type="submit" value="Submit">
</form> 

linux: <form action="/v1/linux-server" method="post">
    <!-- ... -->
    Kernel-version: <input type="text" name="config.kernel-version"><br>
    <input type="submit" value="Submit">
</form>
  

但这真的很放松吗?

“真正放松”与服务器处理请求的方式几乎没有关系-更重要的是了解服务器如何向客户端描述请求(又名hypermedia)。

答案 2 :(得分:0)

我会去s = "Hello world\n\n" s.count('\n') s.strip('\n') 。这样您就可以保留/v1/server/linux作为GET的示例。

/v1/server/windows-如您所说,这将需要更多代码和一些“丑陋的开关盒” 。当有人要求您添加新型服务器时,这种方法也将更难以维护和开发。

/v1/serverPOST : /v1/server-我认为这也是一个好方法。只有2种类型,拥有单独的端点并不重要。与{X1端点}列表相比,/v1/linux-server的数量更大,可读性更好。