REST API最佳实践:如何接受参数值列表作为输入

我们正在推出一个新的REST API,我希望有关社区对最佳实践的投入,以了解如何将输入参数格式化为:

现在,我们的API非常以JSON为中心(只返回JSON)。 关于我们是否需要返回XML的争论是一个单独的问题。

由于我们的API输出是以JSON为中心的,我们一直在走下一条路,在这条路上我们的输入有点以JSON为中心,我一直认为这对一些人来说可能很方便,但总体来说很奇怪。

例如,要获得可以一次拉出多个产品的一些产品详细信息,我们目前有:

http://our.api.com/Product?id=["101404","7267261"]

我们是否应该将其简化为:

http://our.api.com/Product?id=101404,7267261

还是有方便的JSON输入? 更多的痛苦?

我们可能想要接受这两种风格,但这种灵活性是否会导致更多的混乱和头痛(可维护性,文档等)?

更复杂的情况是我们想要提供更复杂的输入。 例如,如果我们想要在搜索上允许多个过滤器:

http://our.api.com/Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}

我们不一定要将过滤器类型(例如productType和颜色)作为请求名称,如下所示:

http://our.api.com/Search?term=pumas&productType=["Clothing","Bags"]&color=["Black","Red"]

因为我们想将所有过滤器输入组合在一起。

最后,这真的很重要吗? 可能有很多JSON实用程序在那里,输入类型并不重要。

我知道我们的JavaScript客户端对API进行AJAX调用可能会喜欢JSON输入以使他们的生活更轻松。


退一步

首先,REST将URI描述为通用唯一ID。 有太多的人被抓住了URI的结构,哪些URI比其他的更“宁静”。 这个论点和说人称“鲍勃”比称他为“乔”更好 - 这两个名字都可以完成“识别一个人”的工作。 URI只不过是一个普遍唯一的名称。

因此,在REST的眼中,争论是否?id=["101404","7267261"]?id=101404,7267261Product101404,7267261更宁静。

现在,话虽如此,多次构建URI通常可以作为RESTful服务中其他问题的良好指示器。 一般来说,你的URI和问题中有几个红旗。

建议

  • 同一资源和Content-Location多个URI

    我们可能想要接受这两种风格,但这种灵活性是否会导致更多的混乱和头痛(可维护性,文档等)?

    URI标识资源。 每个资源应该有一个规范的URI。 这并不意味着你不能有两个URI指向相同的资源,但有明确的方法去做。 如果您决定使用JSON和基于列表的格式(或任何其他格式),则需要决定哪些格式是主要的规范URI。 对指向相同“资源”的其他URI的所有响应都应包含Content-Location标头。

    使用名称类比,拥有多个URI就像为别人提供昵称。 这是完全可以接受的,并且通常时候非常方便,但是如果我使用昵称,我仍然可能想知道他们的全名 - “正式”的方式来指代那个人。 这样当有人提到他们的全名“Nichloas Telsa”时,我知道他们在谈论我称为“尼克”的同一个人。

  • 在你的URI中搜索

    更复杂的情况是我们想要提供更复杂的输入。 例如,如果我们想要在搜索上允许多个过滤器......

    我的一般经验法则是,如果你的URI包含一个动词,它可能表明某些东西是关闭的。 URI标识一个资源,但是他们不应该指出我们对该资源做了什么。 这就是HTTP的工作,或者说我们的“统一接口”。

    为了击败名称类比死亡,在URI中使用动词就像在想要与它们进行交互时改变某人的名字。 如果我与Bob互动,当我想对他说Hi时,Bob的名字不会变成“BobHi”。 同样,当我们想要“搜索”产品时,我们的URI结构不应该从“/ Product / ...”更改为“/ Search / ...”。

  • 回答你的初始问题

  • 关于["101404","7267261"]101404,7267261 :我的建议是为了简单起见,避免使用JSON语法(即,当您不需要时,不要求用户进行URL编码)。 它会让你的API更有用。 更好的是,像其他人所建议的那样,使用标准的application/x-www-form-urlencoded格式,因为它可能是最终用户最熟悉的格式(例如?id[]=101404&id[]=7267261 )。 它可能不是“漂亮”,但漂亮的URI并不一定意味着可用的URI。 但是,重申我的初衷,最终在谈到REST时,并不重要。 不要过分沉迷于此。

  • 您的复杂搜索URI示例可以以与您的产品示例非常相似的方式解决。 我建议再次使用application/x-www-form-urlencoded格式,因为它已经是很多人熟悉的标准。 另外,我会建议合并这两个。

  • 你的URI ...

    /Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}    
    

    被URI编码后的URI

    /Search?term=pumas&filters=%7B%22productType%22%3A%5B%22Clothing%22%2C%22Bags%22%5D%2C%22color%22%3A%5B%22Black%22%2C%22Red%22%5D%7D
    

    可以转化为...

    /Product?term=pumas&productType[]=Clothing&productType[]=Bags&color[]=Black&color[]=Red
    

    除了避免URL编码的要求并使事情看起来更加标准化之外,它现在对API进行了一些均一化处理。 用户知道,如果他们想要检索产品或产品列表(两者都被视为RESTful术语中的单一“资源”),则他们对/Product/... URI感兴趣。


    将值列表作为URL参数传递的标准方法是重复它们:

    http://our.api.com/Product?id=101404&id=7267261

    大多数服务器代码会将其解释为值列表,尽管许多服务器代码都具有单一值简化功能,因此您可能不得不寻找。

    分隔值也可以。

    如果你需要发送JSON到服务器,我不喜欢在URL中看到它(这是一种不同的格式)。 尤其是,URL有一定的大小限制(实际上如果不是理论上的话)。

    我看到有些人用RESTfully做了一个复杂的查询,分两步进行:

  • POST您的查询要求,接收一个ID(实质上创建一个搜索条件资源)
  • GET搜索,并参考上面的ID
  • 如果需要,可以选择删除查询需求,但请注意它们的需求可供重用。

  • 第一:

    我认为你可以通过两种方式做到这一点

    http://our.api.com/Product/<id> :如果你只是想要一个记录

    http://our.api.com/Product :如果你想要所有记录

    http://our.api.com/Product/<id1>,<id2> :正如詹姆斯所建议的,因为产品标签是一个参数

    或者我最喜欢的是:

    您可以使用超媒体作为 RestFul WS 的应用程序状态 (HATEOAS)属性的引擎,并调用http://our.api.com/Product来返回http://our.api.com/Product/<id>的等效url http://our.api.com/Product/<id>并在此之后调用它们。

    第二

    当你不得不对url调用进行查询时。 我会建议再次使用HATEOAS。

    1)打电话给http://our.api.com/term/pumas/productType/clothing/color/black

    2)打电话给http://our.api.com/term/pumas/productType/clothing,bags/color/black,red

    3)(使用HATEOAS)打电话给`http://our.api.com/term/pumas/productType/ - >收到所有可能的网址 - >打电话给你想要的(服装和包) - >接收可能的颜色URL - >调用你想要的颜色

    链接地址: http://www.djcxy.com/p/7965.html

    上一篇: REST API Best practice: How to accept list of parameter values as input

    下一篇: Testing an AJAX POST using Rack::Test