Restful Service和Generic Media Type Payload并保持HATEOAS

时间:2013-06-12 06:01:41

标签: web-services api rest restful-architecture hypermedia

请原谅我,因为我还不熟悉这个RESTFUL的事情,我一直在阅读博客等......他们都有不同的实现/指导方针,只有真正的指导方针才是Richardson成熟度模型,它指明了Hypermedia的含义。 / p>

我知道超媒体设计的好处是通过根URL链接注释驱动机器/用户交互,并且它将像链接更改时一样可以改进,使用幂等/安全的http动词等增强缓存...

我正在尝试设计一个RESTFUL API Web服务,并且我打算使用GENERIC MEDIA TYPE,例如HAL或Collection + Json或Siren等...或者可能创建我自己的媒体类型,我认为我不想马上进入...

使用通用媒体类型,我会有一个有效载荷,一个数据结构或DTO对象,无论你怎么称呼它,比如“具有许多地址的许多申请人模型的应用模型等......”

1)我是否必须在某处指定数据结构定义?或某种表格模板?我已经看到了一些例子,他们把这些数据的定义放在人们可读的格式中,比如“someurl / doc?或者我们应该使用像json schema这样的东西?

2)我见过的一些例子用vcard / foaf等链接中的类型装饰了他们的数据项......例如。 “name”:“http://xmlns.com/foaf/0.1/name”。那是什么意思? 我看到的一些例子就像引用他们的someurl / doc#name来描述名称对象等...

3)是否意味着如果应用程序模型的有效负载发生变化,合同的解释器会发生变化?因此所有客户端都像以前一样破解,就像在SOAP中一样?

4)另一种选择,我认为我可以有一个可进化的项目结构,比如集合+ json项目对象,其中Name,Value,Prompt构成了实际的结构,这样客户端的合同变化最小化消耗它。

请告知我应该如何设计我的对象,基本上说我有一个带有多个地址的应用程序对象以及多个地址来简化问题。

约什

1 个答案:

答案 0 :(得分:3)

目前最好的做法是尽可能避免创建新的内容类型,因此您可以回避这一点。

  1. 取决于您的受众群体。使用他们最容易消费的东西。它们是通用的自动化代理,可以理解架构,还是专门针对API的开发人员。无论如何,你总是需要人类可读的文档,所以我从那里开始。如果您选择接受application/x-www-form-urlencoded请求正文,那么HTML表单将是提供工作模板的绝佳方式。
  2. 这定义了字段的“类型”。因此 namefoaf:name ,它告诉您名为name的字段包含http://xmlns.com/foaf/0.1/name类型的值。您应该阅读有关RDF(资源描述格式)的信息,并查看Turtle和N3之类的表示,这些表示应该更加清晰。虽然链接关系与诸如owl:sameAsfoaf:name之类的RDF属性不同,但是作为URI(而不是简单字符串)的关系的概念来自那里。两者都表示为directed graph中的边。
  3. 请详细说明,您的意思是添加/删除字段还是完全不同的内容类型?我认为后者是一个不同的资源,应该有一个不同的URI。您的客户需要了解或能够忽略您对资源的任何未来更改。
  4. 您建议的所有内容类型都应该以这种方式进行改进。这正是HATEOAS的前提。
  5. 在我看来,您的设计是一个简单的树结构,其中包含一个根资源,其中包含一个集合列表,每个集合都包含一个叶子资源列表。我似乎在这里遗漏了一些东西,因为那里没什么复杂的。

    我将假设申请人是指申请工作的人,而地址是指他们居住或工作的地方(而不是电子邮件地址)。下面的一些内容可能很明显,但我将其包含在可能遇到此问题的其他读者中。

    使用HAL的示例实现将是:

    请求:

    GET / HTTP/1.1
    Host: example.com
    Accept: application/hal+json
    

    响应:

    HTTP/1.1 200 OK
    
    { "_links": {
        "self": { "href": "/" },
        "http://example.com/docs/applicant": [
          { "href": "/applicant1" },
          { "href": "/applicant2" },
          { "href": "/applicant3" }]
    } }
    

    然后客户端会查找具有关系http://example.com/docs/applicant的超链接,这只是一个字符串,如果您愿意,可以是fishmonkeygiraffe - 使字符串成为http URL,允许客户端开发人员找到您的文档更容易,以及通过为其添加唯一字符串前缀来确定关系:您自己的域。 响应格式可以是任何支持超文本的格式,例如HTML,只要客户端知道如何在其中找到超链接(< LINK>和< A>元素),或者您可以在HTTP链接中返回它们如果需要将检索到的资源写入磁盘,则客户端负责存储它们。

    客户端然后请求它想要查看的那个:

    GET /applicant1 HTTP/1.1
    Host: example.com
    Accept: application/hal+json
    

    响应:

    HTTP/1.1 200 OK
    
    { "_links": {
        "self": { "href": "/applicant1" },
        "http://example.com/docs/applicant-address": [
          { "href": "/applicant1/address1" },
          { "href": "/applicant1/address2" },
          { "href": "/applicant1/address3" }]
    } }
    

    显然,“applicant1”可以是你喜欢的任何东西,例如“申请人/ 1”或“职位空缺/甜蜜经理/申请人/戴夫史密斯”。客户端只是遵循它给出的URL。

    然后,客户端会选择类型http://example.com/docs/applicant-address的超链接来检索:

    GET /applicant1/address1 HTTP/1.1
    Host: example.com
    Accept: application/hal+json
    

    响应:

    HTTP/1.1 200 OK
    
    { "_links": {
        "self": { "href": "/applicant1/address1" },
        "edit-form": { "href": "/applicant1/address1/edit" },
        "http://example.com/docs/applicant": { "href": "/applicant1" }
      },
    
      "street": "5 Dungeon Drive",
      "town": "Snotty Hill",
      "county": "London",
      "postcode": "NE5 2LT",
      "country": "GB",
    }
    

    现在客户想要修改地址,因此它遵循带有“edit-form”关系的超链接:(见IANA link relations

    GET /applicant1/address1/edit HTTP/1.1
    Host: example.com
    Accept: text/html
    

    响应:

    HTTP/1.1 200 OK
    
    <!DOCTYPE HTML>
    <form action="/applicant1/address1" method="POST">
      <input name="street" value="5 Dungeon Drive">
      et cetera
    </form>
    

    导致:

    POST /applicant1/address1 HTTP/1.1
    Host: example.com
    Content-Type: application/x-www-form-urlencoded
    
    street=5%20Dungeon%20Drive&...
    

    我使用过HAL,因为HAL就像是XML + XLink的JSON版本,只需输入SO示例就更简单了;)即它是一种支持超媒体的通用解析格式,仅此而已。所有交互都由链接关系引导。 Web浏览器知道如何处理rel="stylesheet"链接,因为它知道该关系意味着什么。以上引用的IANA定义的链接关系列表是您应该首先选择的(itemcollection非常有用),然后如果您要查找的内容不够具体,请尝试查找与您所在行业相关的公共链接关系列表(例如,查看市场领导者发布的API),并在可能的情况下重新使用这些链接关系。这将允许工具变得可互操作,因为它们都在寻找相同的链接关系。您在问题中的都柏林核心示例是公开定义的RDF属性的类似存储库。

    对于超链接,耦合(契约)不是在客户端和您的站点之间,而是客户端和一组关系。这种关系应尽可能众所周知(这就是维基百科在说“对超媒体的一般理解”时的意思。) 对于资源字段,如果您希望对资源进行一般性处理,那么我建议使用基于RDF的解决方案,使用与您的业务领域紧密相关的着名RDF属性。 Several RDF serialisations into JSON exist但目前没有明确的领导者。在这一点上,你可能最好只支持XML。博客文章 JSON to RDF in six easy steps 可能是一种深入了解RDF基础知识的方法。