RESTful API设计争论:对restful端点的复杂查询

时间:2014-10-29 21:54:26

标签: rest restful-architecture

我正在为大量报告数据设计RESTful api,我想传递一组复杂的参数,例如下面的代码块。我正在为此端点使用POST和GET进行辩论。团队成员似乎更喜欢GET,但我不确定将这些数据作为GET参数传递的最佳方法,目前为止最好的想法是将一个GET参数调用为类似jsonparams之类的所有以下json编码

{
  "filters": 
    [
      {
        "field": "metric-name",
        "gt": (float/int),
        "lt": (float/int)
      },
      {
        "field": "metric-name-2",
        "gt": (float/int),
        "lt": (float/int)
      }
    ],
  "sort": 
    [
      {
        "field": "metic-name",
        "order": "ASC"/"DESC"
      },
      {
        "field": "metic-name-2",
        "order": "ASC"/"DESC"
      }
    ]
  "limit": 100,
  "offset": 0
}

2 个答案:

答案 0 :(得分:4)

POST是用于任何未通过HTTP标准化的操作的方法。检索由GET方法标准化,因此使用POST检索与潜在资源相对应的信息永远不会是RESTful。从理论上讲,无论你的URI结果是多么复杂,你都应该使用GET。

但是,由于您执行的查询中没有单一资源可以执行GET,所以只要您了解其中的缺点并且文档清晰明了就可以了。关于它。坦率地说,我认为使用POST比将有效负载编码为JSON + base64并将其作为查询字符串发送仅仅是为了纯粹主义要清晰得多。

使用POST的真正问题是人们以避免或阻止使用真实URI的方式使用它。在您的情况下,这似乎不是问题,因为您有一个有效的集合URI,但查询的语义太复杂,无法轻松表达。

如果您决定使用GET,那就有一个问题。虽然HTTP规范没有对URI建立限制,但大多数实现都会这样做,如果您需要将所有这些参数作为查询字符串提供,则可能会达到该限制。在这种情况下,只要它与您的应用程序分离,它就可以避开底层实现的限制。执行所需操作的约定是将POST方法与上述有效负载以及X-HTTP-Method-Override: GET标头一起使用。

答案 1 :(得分:3)

如果您要将数据添加到资源或创建资源,请使用POST。 GET是获取已存在的资源,而不是更改资源的状态。

  

更新:虽然POST请求可以更新资源,但如果操作是幂等的(意味着不会导致创建新资源,并且每次发出具有相同参数和数据的请求,您都可以保证相同的结果资源),然后建议使用PUT。如果它不是幂等的,但您没有替换整个资源,请使用PATCH(如果只更新资源的一部分)。

如果参数是基于疯狂的序列化GET参数请求某种普遍的简单性,那么你就不会对REST有所了解。

现在,如果您仅检索资源(无创建),请使用GET。虽然我更喜欢人类可打印的参数,但并不是必需的。如果您的情况是100%检索,您可以将整个集合编码为一个巨大的编码参数字符串,但我建议至少将它分解一点以通过执行以下操作来提高理智:

 /resource?filters=urlencoded_filter_array&sort=urlencoded_sort_array&offset=0&count=100

或者你可以更明确地表达:

 /resource?filter1=urlencoded_filter_json&filter2=urlencoded_filter_json .... sort2=urlencoded_sort_json&offset=0&count=100

或者最后(我最喜欢的)一套完全明确的分解参数

 /resource?filter1_field=bah&filter1_gt=1.0&filter1_lt<2&filter2_field=boo&filter2_lt...

我喜欢最后一个,因为没有json的编码/解码,然后url编码整个json字符串。这种格式很容易破解访问日志和故障排除。它也是非常可缓存的,即使参数顺序发生了变化,一些代理缓存仍然可以使用它,而如果json对象中的一些过滤器被移动它们看起来就像完全不同的值那么代理人会担心。对我来说,它是最友好的REST(如果有意义的话),即使前两个例子是很好的REST GET请求。

解析参数名称的附加工作并不是那么大惊小怪。一个简单的方法可以将你的json转换为参数字符串,另一个简单的方法可以从explict filter1_xyz格式重新保存json对象。