背景/上下文:
我有一个非常简单的用例,我试图利用这个机会在我的公司内部为超媒体API开发提供支持。我正在尝试确定 - 在精彩的stackoverflow社区:)的帮助下 - 是我的建议实现是否将所有框称为“RESTful”。
正如所承诺的,用例非常简单 - 我们有一个数据表,我们在每个zipcode的基础上跟踪某种位置分类代码。关于这张表唯一有趣的是我们通过from / thru日期有效的概念:
表状态1
ID | ZIP | CODE | FROM | THRU
====|======|======|===========|===========
548 |90210 |R |2013-01-01 |null
我们每年秋季都会获得更新数据,该数据将于次年1月1日生效。例如,如果上述邮政编码被更新为新的“CODE”值,我们将对下表进行更改:
表状态2
ID | ZIP | CODE | FROM | THRU
====|======|======|===========|===========
548 |90210 |R |2013-01-01 |2014-12-31
777 |90210 |U |2015-01-01 |null
当然,可以将这种交互作为CRUD服务在他们的睡眠中公开,称之为“RESTful”,并在短时间内完成。 PUT更新旧记录的“THRU”日期; POST以插入反映新数据的记录。
很简单,但正如我所提到的,我正在尝试利用这个机会进行超媒体案例研究 - 这是我提出的设计(通过一些样本请求传达)。以下是我建议从表状态1 到表状态2 的建议:
请求1:
GET /zips/90210
回复1:
200 OK
{"zipCode":90210,"pickupLocationCode":"R","fromDate":"2013-01-01","thruDate":null,
"_links":{"self":{"href":"/zips/90210"},
"latest":{"href":"/zips/90210"}}}
请求2:
PUT /zips/90210
{"zipCode":90210,"pickupLocationCode":"U","fromDate":"2015-01-01","thruDate":null}
回应2:
204 No Content
请求3:
GET /zips/90210
回应3:
200 OK
{"zipCode":90210,"pickupLocationCode":"U","fromDate":"2015-01-01","thruDate":null,
"_links":{"self":{"href":"/zips/90210"},
"previous":{"href":"/zips/90210/0"},
"latest":{"href":"/zips/90210"}}}
请求4:
GET /zips/90210/0
回应4:
200 OK
{"zipCode":90210,"pickupLocationCode":"R","fromDate":"2013-01-01","thruDate":"2014-12-31",
"_links":{"self":{"href":"/zips/90210/0"},
"next":{"href":"/zips/90210"},
"latest":{"href":"/zips/90210"}}}
请注意,请求2中的PUT会自动“过期”旧行(即设置截止日期),然后插入新行。
我试图允许客户端(1)使用知名的业务密钥(例如“90210”)通过URL定位给定的邮政编码,然后通过超媒体(“下一个”,“上一个”, “最新”链接rels),允许客户端在不同时间点浏览邮政编码的各种状态。我是走在正确的道路上还是傻瓜的差事?
使用这种设计,如果你想要“删除”一个邮政编码(我很少猜测 - 如果有的话? - 发生了,但是再一次,尝试将其用作学术活动而不是任何东西),你可以做一些有趣的事情:
删除请求:
DELETE /zips/90210
删除回复:
204 No Content
随后对/ zips / 90210的GET会给你:
303 See Other
Location: /zips/90210/0
这将使您能够区分(1)我们不再拥有任何“活动”数据的邮政编码和(2)从未存在的邮政编码 - 例如:
GET /zips/99999
哪会给你一个好老404:
404 Not Found
插入一个新的邮政编码(可能 半频繁发生的用例)只需要进行探索性GET以确认zip目前不存在(即303请参阅其他或404 Not Found响应,然后对基础“/ zips”URL进行POST。
非常感谢任何反馈!