对于 RESTful 服务 - 客户端如何找到资源属性的有效值?

For a RESTful service - How does a client find valid values for a resource attribute?

作为 RESTful API 提供的资源的功能发现的一部分,我正在寻找一种方法让服务宣布接受的属性值。考虑以下示例,其中 apple 资源具有属性 color:

GET /apples/17

此请求产生:

{
  "name": "My yummy apple",
  "color": "green"
}

为了让客户理解什么 color 值是有效的,例如 PUT 使用这个苹果的新版本,我可以想出很多可能的方法。但是我在这里没有找到任何最佳实践。 HTTP OPTIONS 动词似乎不是为这种细粒度的发现而设计的。我应该只向 /apples 集合添加一个数组属性吗:

GET /apples

回复:

{
  ...
  "colorValues": ["red", "green"]
}

有没有更好更常用的方法?

编辑: 刚刚意识到一种可能的方法是为所有 "real" 资源的模式添加资源。 GET /schemas/apple 之类的东西会为 apple 资源生成 JSON 模式表示。 json-schema.org:

的修改示例
{
    "id": "http://foo.bar/schema#",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "schema for an apple resource",
    "type": "object",
    ...
    "colorValues": {
        "enum": [ "red", "green" ]
    }
}

虽然我还没有找到任何这样的例子。

一种可能的方法是拥有两种资源:applescolours。您的潜在客户可以很容易地以 restful 的方式获得可用的颜色。超媒体呢?有 many standards,您可以创建自己的,但最好坚持使用一些 widely-used。

例如,如果你想在HAL之后实现它,获取苹果将如下所示:

GET /apples/17

{
  "name": "My yummy apple",
  "_links": {
     "self": {
       "href": "/apples/17"
     },
   },
   "colour": {
     "id": "green",
     "href": "/colours/green"
   }
}

列出所有颜色怎么样?像这样:

GET /colours

{
  "_links": {
    "self": {
        "href": "/colours"
    }
  },
  "_embedded": {
    "colours": [
      {
         "_links": {
           "self": {
             "href": "/colours/green"
           }
         },
         "id": "green"
      },
      {
         "_links": {
           "self": {
             "href": "/colours/red"
           }
         },
         "id": "red"
      }
    ]
  }
}

这是设计 API 的现代方法,例如 Amazon

The Amazon AppStream web service is a resource-based API that uses Hypertext Application Language (HAL). HAL provides a standard way for expressing the resources and relationships of an API as hyperlinks. Using HAL, you use HTTP methods (GET, PUT, POST, DELETE) to submit requests and receive information about the API in the response. Applications can use the information returned to explore the functionality of the API.

编辑:

如果允许不同的实体使用不同的颜色,你可以这样做

GET /apples/17

{
  "name": "My yummy apple",
  "_links": {
     "self": {
       "href": "/apples/17"
     },
     "available_colours": {
       "href": "/apples/17/available_colours"
     }
   },
   "colour": {
     "id": "green",
     "href": "/colours/green"
   },      
   "_embedded": {
     "available_colours": [
       {
         "_links": {
           "self": {
             "href": "/colours/green"
           }
         },
         "id": "green"
       },
       {
         "_links": {
           "self": {
             "href": "/colours/red"
           }
         },
         "id": "red"
       }
    ]
  }
}

如您所见,它的结构非常灵活。

JSON Hyper-Schema 非常适合这种事情。

GET /apples/17
HTTP/1.1 OK
Content-Type: application/json; profile="/schema/apple"

{
  "id": 17,
  "name": "My yummy apple",
  "color": "green"
}

然后客户端可以取消引用 schema/apple 处的 hyper-schema 以了解接下来有哪些 link 可用。

GET /schema/apple
HTTP/1.1 OK
Content-Type: application/schema+json

{
  "id": "http://foo.bar/schema/apple",
  "$schema": "http://json-schema.org/draft-04/hyper-schema#",
  "type": "object",
  "properties": {
    "id": { "type": "string", "readOnly": true },
    "name": { "type": "string" },
    "color": { "enum": ["red", "green"] }
  },
  "required": ["id", "name", "color"],
  "links": [
    { "rel": "self", "href": "/apple/{id}" },
    {
      "rel": "http://foo.bar/relation/edit",
      "href": "/apple/{id}",
      "method": "PUT",
      "schema": { "$ref": "#" }
    }
  ]
}

这是一个您熟悉的 JSON 架构,但包含一个额外的关键字 links,它描述了您可以从此资源中获取的 link。客户端使用来自原始 JSON 数据的值评估 href URI 模板。因此,在这种情况下,link 的计算结果为 ...

{
  "rel": "http://foo.bar/relation/edit",
  "href": "/apple/17",
  "method": "PUT",
  "schema": { "$ref": "#" }
}

此 link 指示客户端可以向 /apple/17 发出 PUT 请求,并且请求正文应针对 /schema/apple 处的架构进行验证({ "$ref": "#" } 表示此模式)。

这为您提供了人类可读和机器可执行的功能描述。机器可执行部分很重要,因为通常可以在不破坏现有客户端的情况下对您的 API 进行更改。

注意:此代码是在 JSON Hyper-Schema draft-04 中编写的。最近有一个新版本 draft-05 出来了。它进行了一些有争议的更改。在这一点上,我仍然推荐 draft-04。可以在 https://datatracker.ietf.org/doc/html/draft-luff-json-hyper-schema-00.

找到规范