简体   繁体   English

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

[英]REST API POST/PUT with different set of requests

Can a post or put method that creates / modifies resource can accept different set of request objects? 创建/修改资源的post或put方法能否接受不同的请求对象集?

For eg: I have a resource called 'server' . 例如:我有一个名为'server'的资源。 It can be distinguished by its os. 它可以通过os来区分。 for example I can have two resource instances - a windows server and a linux server . 例如,我可以有两个资源实例windows serverlinux server My basic decision here is to treat them as same type of resource ie server . 我在这里的基本决定是将它们视为相同类型的资源,即server

Now it may happen that to create a windows server my POST API accepts request object that is different from what that same API would take for linux server. 现在可能会发生,创建Windows服务器时,我的POST API接受的请求对象与该API用于Linux服务器的请求对象不同。

For creating windows server I have - 对于创建Windows服务器,我有-

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

For creating linux server I use same api but consume different request object - 为了创建Linux服务器,我使用相同的api,但是使用了不同的请求对象-

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

As you can see requests accepted by same POST API are different for windows and linux server. 如您所见,Windows和Linux服务器的相同POST API接受的请求不同。 My business logic will handle these request based on 'os' attribute. 我的业务逻辑将基于'os'属性处理这些请求。 So technically, it will work (with ugly switch cases). 因此,从技术上讲,它将起作用(使用难看的开关盒)。 But is it truly restful? 但这真的令人放松吗? Or I should have different APIs like /v1/windows-server and /v1/linux-server and have unique request definitions defined for each of them? 还是我应该拥有不同的API,例如/v1/windows-server/v1/linux-server并为每个API定义唯一的请求定义?

From client's POV it's better to have one endpoint. 从客户的角度来看,最好有一个端点。 Note that having separate resources would move the neccessity of "ugly switching" to the client. 请注意,拥有单独的资源会将“丑陋切换”的必要性转移到客户端。

I'd go with your current solution. 我会采用您当前的解决方案。 Client's convienience and API clarity/simplicity is more important than developer's. 客户的便利性和API的清晰性/简洁性比开发人员的更为重要。 API is more important than implementation. API比实现更重要。 And IMHO your current solution is better in this regard: 恕我直言,您当前的解决方案在这方面更好:

  • create: POST /v1/servers 创建: POST /v1/servers
  • fetch: GET /v1/servers/{server_id} POST /v1/servers/{server_name} (given name is unique) returns single resource 获取: GET /v1/servers/{server_id} POST /v1/servers/{server_name} (给定名称是唯一的)返回单个资源
  • query: GET /v1/servers/?{filter_expression} (eg GET /v1/servers/?os=linux ) returns collection of (filtered) resources (preferably with pagination) 查询: GET /v1/servers/?{filter_expression} (例如GET /v1/servers/?os=linux )返回(过滤的)资源的集合(最好是分页)

One thing I'd change is I'd extract the OS-specific stuff to a nested resource. 我要更改的一件事是,将特定于操作系统的内容提取到嵌套资源中。 This will make the implemenation simpler and the API even clearer: 这将使实现更加简单,API更加清晰:

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

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

But is it truly restful? 但这真的令人放松吗?

A good way to test that question, is to ask how closely what you are trying to do matches the web. 测试该问题的一种好方法是,询问您要做什么与网络相匹配。

In this case, the analog would be to have two different forms that submit requests to the same target URI described the by the form action attribute. 在这种情况下,类似物将具有两种不同的形式,这些形式将请求提交给由表单动作属性描述的同一目标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>

Any standards compliant web client will handle that just fine. 任何符合标准的Web客户端都可以处理。 The processing rules for the text/html media type tell the client how to construct a request from each of these forms. text/html媒体类型的处理规则告诉客户端如何从这些形式中的每一个构造请求。

Notice that because the browser is just processing the form.action, you can easily change the resource identifier. 请注意,由于浏览器仅在处理form.action,因此您可以轻松更改资源标识符。 So if you later decide that windows and linux requests should use different requests, you can do that easily enough: 因此,如果您以后决定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>

But is it truly restful? 但这真的令人放松吗?

Being "truly restful" has relatively little to do with how your server handles a request -- what is much more important is understanding how the server describes requests to the client (aka hypermedia ). “真正的放松”与服务器处理请求的方式几乎没有关系,更重要的是了解服务器如何描述对客户端的请求(又名超媒体 )。

I would go for /v1/server/linux and /v1/server/windows . 我会去/v1/server/linux/v1/server/windows This will allow you to keep /v1/server for example for GET. 例如,这将使/v1/server保持GET。

POST : /v1/server - as you have said, this would require more code and some "ugly switch cases" . POST : /v1/server如您所说,这将需要更多代码和一些“难看的开关盒” This approach will be also harder to maintain and develop when someone will request you to add new types of servers. 当有人要求您添加新型服务器时,也很难维护和开发这种方法。

/v1/linux-server and /v1/windows-server - I think it is also good approach. /v1/linux-server/v1/windows-server我认为这也是一种好方法。 With just 2 types it is not a big deal to have separate endpoints. 只有2种类型,拥有单独的端点并不重要。 With the larger number, /v1/server/{os_type} looks better in documentation and is more readable than the list of X separate endpoints. 数量越大, /v1/server/{os_type}文档记录越好,并且比X个单独的端点列表更易读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM