如何创build没有动词的RESTurl?
我正在努力确定如何devise宁静的url。 我是所有的使用URL名词的宁静的方式,而不是动词不明白如何做到这一点。
我们正在创build一个服务来实现一个金融计算器。 计算器需要一些参数,我们将通过CSVfile upload。 用例包括:
- 上传新的参数
- 获取最新的参数
- 获取给定业务date的参数
- 使一组参数处于活动状态
- validation一组参数
我收集宁静的方法将是有以下types的url:
/parameters /parameters/12-23-2009
您可以通过以下方式实现前三个用例:
- POST请求中包含参数文件的位置
- 获取第一个url
- 获取第二个url
但是,你如何做第四和第五个没有动词的用例呢? 你不需要像这样的url:
/parameters/ID/activate /parameters/ID/validate
??
也许是这样的:
PUT /parameters/activation HTTP/1.1 Content-Type: application/json; encoding=UTF-8 Content-Length: 18 { "active": true }
好的URIdevise的一般原则:
- 不要使用查询参数来改变状态
- 如果可以帮助的话, 不要使用混合path。 小写是最好的
- 不要在URI中使用特定于实现的扩展(.php,.py,.pl等)
- 不要使用您的URI进入RPC
- 尽可能限制你的URI空间
- 请保持path短
- 首选
/resource
或/resource/
; 从你不使用的那个创build301redirect - 请使用查询参数来进行资源的子select。 即分页,search查询
- 将东西移出应该位于HTTP标头或正文中的URI
(注:我没有说“RESTful URIdevise”; URI在REST中本质上是不透明的。)
HTTP方法select的一般原则:
- 永远不要使用GET来改变状态; 这是让Googlebot毁了你一天的好方法
- 除非你正在更新整个资源,否则不要使用PUT
- 不要使用PUT,除非你也可以在同一个URI上合法地做一个GET
- 不要使用POST检索长寿命或可能合理caching的信息
- 不要执行与PUT不等幂的操作
- 尽可能使用GET
- 如有疑问,请优先使用POST
- 当你必须做一些感觉类似于RPC的事情时,请使用POST
- 对于较大或分层的资源类,请使用PUT
- 使用DELETE优先于POST来删除资源
- 除非你的input很大,否则使用GET来计算,在这种情况下使用POST
使用HTTP进行Web服务devise的一般原则:
- 不要将元数据放在应该在标题中的响应的正文中
- 不要将元数据放在单独的资源中,除非包含它会造成重大的开销
- 请使用适当的状态码
-
201 Created
资源后创build; 资源必须在发送响应时存在 -
202 Accepted
成功执行操作或asynchronous创build资源后202 Accepted
- 当有人对显然是虚假的数据进行操作时,
400 Bad Request
; 对于你的应用程序,这可能是一个validation错误; 一般为未捕获的exception保留500个 -
401 Unauthorized
当有人访问您的API时401 Unauthorized
而未提供必要的Authorization
标头或Authorization
内的凭证无效; 如果您不希望通过Authorization
标头获得凭据,请不要使用此响应代码。 -
403 Forbidden
当某人以恶意或未经授权访问您的API时被禁止 -
405 Method Not Allowed
有人使用POST时应该使用PUT等 -
413 Request Entity Too Large
当有人试图向您发送一个不可接受的大文件 - 当试图用茶壶冲泡咖啡时,
418 I'm a teapot
一个茶壶
-
- 尽可能使用caching标题
- 当您可以轻松地将资源减less到散列值时,
ETag
头是很好的 -
Last-Modified
应该告诉你,保持资源更新的时间戳是个好主意 -
Cache-Control
和Expires
应该被赋予合理的值
- 当您可以轻松地将资源减less到散列值时,
- 尽你所能地在一个请求中声明caching标题(
If-None-Modified
,If-Modified-Since
) - 有意义时使用redirect,但这些对于Web服务来说应该是罕见的
关于你的具体问题,POST应该用于#4和#5。 这些操作属于上述“类RPC”指导方针。 对于#5,请记住,POST不一定必须使用Content-Type: application/x-www-form-urlencoded
。 这可以很容易地是一个JSON或CSV有效载荷。
只要看起来你需要一个新的动词,考虑把这个动词变成一个名词来代替。 例如,将“激活”转为“激活”,将“validation”转换为“validation”。
但是从你写的东西我会说你的应用程序有更大的问题。
任何时候提出一个名为“参数”的资源,都应该在每个项目组成员的头脑中发出红旗。 '参数'可以从字面上适用于任何资源; 这不够具体。
“参数”究竟代表什么? 可能有许多不同的东西,每个东西都应该有一个独立的资源。
解决这个问题的另一种方法是,当你和最终用户讨论你的应用时(那些对编程知之甚less的人)他们自己反复使用的词是什么?
这些是你应该围绕你的应用程序devise的词汇。
如果您还没有与潜在用户进行这种转换,请立即停止所有操作,直到您完成后再写一行代码! 只有这样,你的团队才能明白需要build立什么。
我对财务软件一无所知,但如果我不得不猜测,我会说一些资源可能会通过名称,如“报告”,“付款”,“转账”,“货币”。
在软件devise过程的这一部分有许多好书。 我可以推荐两个域驱动devise和分析模式 。
您的url的devise与您的应用程序是否为RESTful无关。 因此短语“RESTful URL”是无稽之谈。
我认为你应该多做一些REST实际上的阅读。 REST将URL视为不透明的,因此不知道它们是什么,不pipe是动词还是名词,或者其他什么。 你可能仍然想要devise你的URL,但这是关于UI,而不是REST。
这就是说,让我们来看看你的问题:最后两种情况是不是RESTful,不适合任何一种宁静的scheme。 这些就是你可能称之为RPC的东西。 如果你认真对待REST,你将不得不重新思考你的应用程序是如何工作的。 要么,要么放弃REST,只是做你的应用程序作为一个RPC应用程序。
Hrmmm可能不是。
这里的想法是,你必须把所有的东西当作一个资源来处理,所以一旦一组参数有一个你可以参考的URL,你只需要添加
获取[parametersurl] / validationresults
后[paramatersurl]
body:{command:“activate”}
但是,再次激活的东西是RPC,而不是REST。
激活和validation要求是您尝试更改资源状态的情况。 订单“完成”或其他一些“提交”请求也不例外。 有许多方法可以模拟这种状态变化,但是我发现经常工作的方法是为相同状态的资源创build集合资源,然后在集合之间移动资源以影响状态。
例如创build一些资源,
/ActiveParameters /ValidatedParameters
如果要使一组参数处于活动状态,请将该设置添加到ActiveParameters集合中。 您可以将参数集作为实体正文传递,也可以将url作为查询parameter passing,如下所示:
POST /ActiveParameters?parameter=/Parameters/{Id}
/ ValidatedParameters可以做同样的事情。 如果参数无效,则服务器可以向请求添加“错误请求”,以将参数添加到已validation参数的集合中。
我会build议下面的元资源和方法。
使参数激活和/或validation它们:
> PUT /parameters/<id>/meta HTTP/1.1 > Host: example.com > Content-Type: application/json > Connection: close > > {'active': true, 'require-valid': true} > < HTTP/1.1 200 OK < Connection: close <
检查参数是否有效且有效:
> GET /parameters/<id>/meta HTTP/1.1 > Host: example.com > Connection: close > < HTTP/1.1 200 OK < Content-Type: application/json < Connection: close < < { < 'active': true, < 'require-valid': true, < 'valid': {'status': false, 'reason': '...'} < } <
在REST环境中,每个URL都是唯一的资源。 你有什么资源? 金融计算器确实没有任何明显的资源。 您需要深入了解您所调用的参数并提取资源。 例如,贷款的摊销日历可能是一种资源。 日历的URL可能包括start_date,term(以月份或年份),period(当利息被复合时),利率和初始原则。 所有这些值都有一个特定的付款日历:
http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000
现在,我不知道你在计算什么,但是你的参数列表的概念听起来不是RESTful。 正如别人所说,你的要求听起来更XMLRPC。 如果你正在尝试REST,你需要名词。 计算不是名词,它们是对名词起作用的动词。 你需要把它翻过来把名词拉出你的计算。
编辑:确实,URI将阻止GET
请求保持幂等。
然而,对于validation,使用HTTP状态代码来通知请求的有效性(创build新的或修改现有的'参数')将适合于Restful模型。
如果提交的数据无效并且请求必须在重新提交之前被更改( HTTP / 1.1状态码 ),则返回400 Bad Request
状态码。
这依赖于在提交时确认,而不是像在你的用例那样推迟。 其他答案对这种情况有适当的解决scheme。