我正在尝试定义REST API,但我遇到了一个问题。 我有一个API用户可以执行的操作是相同的,但可以通过两种不同的方式完成。
例如,假设我的用户使用我的API来改变灯光的强度。我将有一个类似
的URLAPI /光/强度
用户必须更改强度的一个选项是设置为最大亮度的%,另一个选项是将强度设置为精确值,以流明(有一个检测器)并且他可以通过“精确度”可以是低,中,高(它会改变达到正确强度所需的时间)。
我希望用户能够获得当前的强度,这意味着他在哪种模式下,取决于模式,%或流明的值和精度。
这是我丢失的地方,我的GET将返回一个JSON对象,例如,发送类似
的内容是否可以{
"Mode" = "Percent",
"Percent" = 50.5
}
当我处于“百分比”模式和
时{
"Mode" = "Exact",
"Lumens" = 200,
"Precision" = "High"
}
当我处于“流明”模式时?
如果这似乎没问题,我该如何告诉用户他应该解析哪种类型的“对象”?
让用户发送更改的最佳方法是什么?我在考虑有两个URL,每个模式一个,比如 PUT / api /光/强度/精确和PUT / api /光/强度/百分比
两者都在等待与上面类似的JSON对象,没有模式。
答案 0 :(得分:8)
使用HTTP Content negotiation。这允许:
GET
,PUT
服务器。定义两种供应商内容类型:
application/vnd.com.example.light.intensity.percentage+json
application/vnd.com.example.light.intensity.lumens+json
客户端告诉服务器它想要哪一个:
GET /api/light/intensity/
Accept: application/vnd.com.example.light.intensity+percentage
服务器响应:
200 OK
Content-Type: application/vnd.com.example.light.intensity+percentage
{
"Percent" = 50.5
}
客户希望改变强度:
PUT /api/light/intensity/
Content-Type: application/vnd.com.example.light.intensity+percentage
{
"Percent" = 42.7
}
服务器从Content-Type
标头知道如何解释JSON主体。在此示例中,它以“百分比”模式处理请求。
如果使用了第二种内容类型,客户端和服务器就会知道在“Lumes”模式下解释请求/响应。
修改:请注意GET
和PUT
请求使用相同的网址,因为请求的资源大致相同:光照强度。所有不同的是此资源的表示。处理此问题的正确方法是内容类型。
答案 1 :(得分:-1)
具体细节取决于您的API以及用户的需求。对RESTful API的相同GET方法调用应始终返回相同的值:由URL中的信息定义的资源表示,而不是其他任何内容。 如果你在系统中保持状态,你就违反了REST的规则。(编辑:正如Gimly指出的那样,这个陈述不清楚。它不是一个违反RESTful设计以保持系统自身的内部状态,尤其是当请求使用PUT
,POST
或DELETE
更改系统状态时。这违反了请求依赖该状态返回资源的表示,或请求状态更改。每个请求应该是自包含的。)
我使用查询字符串来更改表示的格式:
GET /api/light/intensity
GET /api/light/intensity?f=percent
那样/api/light/intensity
始终引用相同的资源(默认为“精确”表示,其具有最多数据),并且查询字符串“过滤”表示,类似于搜索查询。它删除了一些数据(在这种情况下,确切的亮度和精度),有利于相对表示,以某个最大值的百分比表示。或者,您可以将其视为控制输出格式:GET /foo.json
vs GET /foo.xml
。资源相同,但表示不同。
要更新资源,您可以按照自己的描述获取对象。您的服务器必须了解不同的格式,但您可以PUT
到裸URL,或者再次使用查询参数来控制服务器所期望的格式,然后使用{使您的有效负载更抽象{1}}代替value
或lumens
:
percentage
这允许您以PUT /api/light/intensity
Payload: {"value": 200, "precision": "high"}
PUT /api/light/intensity?f=percent
Payload: {"value": 50.5}
是资源的一个属性的方式构建light
资源的API。 “百分比”然后成为输出中的便利表示,因此当您返回整个intensity
资源时,它将读取如下内容:
light
因此API用户可以根据"light": {
"name": "the light",
"id": 12345,
"intensity": 200,
"max-intensity": 400,
...
}
和intensity
计算当前百分比。 (当然,您可以将“百分比”替换为“最大强度”并让用户以其他方式进行数学运算,但我觉得提供绝对值并让数学计算相对值更自然。
修改强>
请参阅Tichodroma的答案,以便更好地处理此问题。我要留下答案,因为评论中的讨论对我很有用,将来可能对其他人有用。