jow*_*wee 8 rest api-design hateoas
我在这里看了很多关于SO的讨论,观看了Jon Moore的演讲(其中解释了很多,顺便说一句),并阅读了Roy Fielding关于HATEOAS的博客文章,但在客户端设计方面,我仍然感到有点暗淡.
API问题
现在,我只是返回带有表单/锚点和定义列表的xhtml来表示资源.以下代码段详细说明了我如何布置表单/锚点/列表.
# anchors
<li class='docs_url/#resourcename'>
<a rel='self' href='resource location'></a>
</li>
# forms
<form action='action_url' method='whatever_method' class='???'></form>
# lists
<dl class='docs_url/#resourcename'>
<dt>property</dt>
<dd>value</dd>
</dl>
Run Code Online (Sandbox Code Playgroud)
我的问题主要是表格.在Jon的演讲中,他记录了诸如(add_location_form)等表单类型以及它们所需的输入.我没有很多资源,但我正在考虑抽象表单类型(添加,删除,更新等),并在文档中注意,(添加,更新)您必须发送目标资源的有效表示并删除,您必须发送标识符.
问题1:有了HATEOAS的概念,我们真的不应该让客户"发现"表单(通过对它们进行分类添加,删除,更新等)并只发送回我们给他们的所有数据吗?我在这里的真正问题(不是一个讨论)是否遵循良好做法?
客户问题
在HATEOAS之后,我们对可以发现的资源采取的行动如何影响客户端代码(api的消费者)及其ui.听起来很棒,按照这些原则,UI应该只显示可用的操作但是如何实现?
我目前的方法是将响应解析为xml和usin xpath,以查找客户端开发时已知的操作(记录的表单类,即添加,删除,更新),并显示ui控件(如果可用).
问题2:我的发现方式错了吗?或者就客户而言(知道表单类),这太过神奇吗?这不会假设客户端知道哪些操作可用于每个资源(这可能没问题,因为它是创建客户端的一种原因,对吗?)并且应该记录操作(表单类)到资源的映射,或只是记录表单类,并允许客户端(和客户端开发人员)研究和发现它们?
我知道我到处都是这个,但任何见解都非常感激.我会回答一个回复,回答这两个问题中的任何一个.谢谢!
不,你很喜欢.
浏览器只是渲染HTML有效负载,并依赖于人类实际解释,找到意义,并可能适当地填充表单.
到目前为止,机器客户往往在"解释"部分做得非常糟糕.因此,开发人员必须提前做出决策并引导机器客户端处于难以理解的细节中.
理想情况下,"智能"HATEOS客户端会拥有某些事实,并了解上下文,以便更好地将这些事实映射到服务的要求.
因为那就是我们做的,对吧?我们看到一个表格"哦,他们想要姓名,地址,信用卡号码".我们不仅知道"姓名","地址"和"信用卡"号码是什么意思,我们也可以知道他们的意思是我的名字,或者信用卡上的人的姓名,或者被运送的人的姓名至.
机器也很容易在"直觉"部分失败.因此,作为开发人员,您可以根据您认为可能需要的逻辑来编写代码,以确定正确的事实以及它们的放置方式.
但是,回到理想的客户端,它会看到每个表单,"知道"字段所需的内容,查阅其内部的"事实"列表,然后正确填充请求的有效负载,最后发出请求.
您可以看到,一个简单而明显易碎的方法是简单地将参数名称映射到内部数据.当参数名称为"name"时,您可以将其硬编码为:firstName +""+ lastName.或者您可以认为实际的rel"知道"他们正在谈论运输,并使用:shipTo.firstName +""+ shipTo.lastName.
随着时间的推移,理想情况下你可以建立一个映射集合,这样如果突然有效负载引入了一个新字段,而它恰好是你已经知道的字段,你可以"自动"填写它而不需要改变客户端.
但简单的事实是,虽然这可以做到,但几乎没有完成.语义通常是模糊的方式,你必须每次为每个新的有效载荷编写新的"直觉"代码,所以你也可以直接编写有效载荷并完成它.
但关键是,尤其是关于HATEOS的问题是,您不要将数据"强制"到服务器上.服务器告诉你它想要什么,特别是如果他们给你你的表格.
所以思考过程不是"哦,如果我想要一个发货发票,我看到,现在,他们想要名称,地址和订单号,他们想要它编码的URL,他们希望它发送到http://示例.com/shipping_invoice.所以我总是发送:姓名+"&"+地址+"&"+ orderNumber每次到http://example.com/shipping_invoice.轻松!".
而你想要做的是"我看到他们想要一个姓名,地址和订单号.所以我要做的就是每个请求,我会阅读他们的表格.我会检查他们每次都想要的字段.如果他们想要名字,我会给他们名字.如果他们想要地址,我会给他们地址.如果他们想要订单编号,我会给他们订单编号.如果他们有任何PRE-POPULATED字段(甚至"隐藏"字段) ,我也会把它们发回来,我会按照他们要求的编码发送它,假设我支持它,从我从FORM标签的action字段获得的URL."
您可以在前一种情况下看到,您每次都希望他们想要有效载荷.就像你在硬编码URL一样.而对于第二个,也许他们认为名称和地址是多余的,所以他们不再要求它.也许他们为你可能不支持的新功能添加了一些不错的默认值.也许他们将编码改为多部分?或者更改了端点URL.谁知道.
您只能在编写客户端代码时发送您所知道的内容,对吗?如果他们改变了事情,那么你只能做你能做的事情.如果他们添加字段,希望他们添加不需要的字段.但是,如果他们打破了界面,嘿,他们打破了界面,你就会记录错误.你可以做的不多.
但是你利用HATEOS部分的次数越多,它们就越多,你可以更灵活:填写表格,正确地重定向,注意编码和媒体类型,你的客户就越灵活.
最后,大多数人根本不会在他们的客户中这样做.他们硬编码,因为它很简单,并且他们认为后端没有足够快速变化,或者如果发生这种变化,任何停机时间都可以接受,直到他们纠正客户端为止.更典型的是,特别是对于内部系统,您只需从开发人员那里收到一封电子邮件"嘿正在更改XYZ API,它将于3月1日上线.请在集成测试期间更新您的客户并与发布团队协调.kthx".
这才是现实.这并不意味着你不应该这样做,或者你不应该让你的服务器对更聪明的客户更友好.记住一个糟糕的客户端,假设一切都不会使一个好的基于REST的系统失效.这些系统适用于糟糕的客户端.wget ftw,是吗?
归档时间: |
|
查看次数: |
2424 次 |
最近记录: |