我正在努力确定如何设计restful URL . 我完全是为了使用带名词的URL而不是动词的安静方法不明白如何做到这一点 .
我们正在创建一个实施金融计算器的服务 . 计算器采用一系列参数,我们将通过CSV文件上传 . 用例包括:
-
上传新参数
-
获取最新参数
-
获取给定营业日期的参数
-
激活一组参数
-
验证一组参数
我收集的其余方法是拥有以下类型的URL:
/parameters
/parameters/12-23-2009
您可以通过以下方式实现前三个用例:
-
POST,在post请求中包含参数文件
-
第一个网址的GET
-
获取第二个URL
但是,如果没有动词,你如何做第4和第5个用例?你不需要像以下网址:
/parameters/ID/activate
/parameters/ID/validate
??
8 回答
也许是这样的:
良好URI设计的一般原则:
Don't 使用查询参数来改变状态
Don't 如果可以帮助它,请使用混合大小写路径;小写是最好的
Don't 在URI(.php,.py,.pl等)中使用特定于实现的扩展
Don't 与您的URI一起落入RPC
Do 尽可能限制您的URI空间
Do 保持路径段短
Do 更喜欢
/resource
或/resource/
;从您不使用的重定向创建301重定向Do 使用查询参数进行资源的子选择;即分页,搜索查询
Do 移出应该在HTTP标头或正文中的URI
(注意:我没有说“RESTful URI设计”; REST在REST中基本上是不透明的 . )
HTTP方法选择的一般原则:
Don't 曾使用GET改变状态;这是让Googlebot破坏你的一天的好方法
Don't 除非您要更新整个资源,否则请使用PUT
Don't 使用PUT,除非你也可以在同一个URI上合法地进行GET
Don't 使用POST来检索长期存在或可能合理缓存的信息
Don't 使用PUT执行不是idempotent的操作
Do 尽可能使用GET
Do 在有疑问时使用POST而不是PUT
Do 只要你需要做类似RPC的事情就使用POST
Do 将PUT用于较大或分层的资源类
Do 优先使用DELETE删除资源
Do 使用GET进行计算之类的事情,除非输入很大,在这种情况下使用POST
使用HTTP进行Web服务设计的一般原则:
Don't 将元数据放在应该位于 Headers 中的响应正文中
Don't 将元数据放在单独的资源中,除非包含它会产生大量开销
Do 使用适当的状态代码
创建资源后
201 Created
;资源 must 在发送响应时存在成功执行操作或异步创建资源后
202 Accepted
400 Bad Request
当某人对明显虚假的数据进行操作时;对于您的应用程序,这可能是一个验证错误;通常为未捕获的例外保留500401 Unauthorized
当有人访问您的API时,如果没有提供必要的Authorization
标头,或者Authorization
中的凭据无效;不要通过Authorization
标头来获取凭据 .403 Forbidden
当某人以恶意或未经授权的方式访问您的API时405 Method Not Allowed
当有人使用POST时应该使用PUT等413 Request Entity Too Large
当有人试图向您发送一个不可接受的大文件时418 I'm a teapot
when attempting to brew coffee with a teapotDo 尽可能使用缓存标头
当您可以轻松地将资源减少为哈希值时,
ETag
标头很好Last-Modified
应该向您表明,保持资源更新时间的时间戳是一个好主意Cache-Control
和Expires
应该给出明智的 ValueDo 您可以在请求中尊重缓存标头的所有内容(
If-None-Modified
,If-Modified-Since
)Do 在有意义时使用重定向,但这对于Web服务来说应该是罕见的
关于您的具体问题,POST应该用于#4和#5 . 这些操作属于上述"RPC-like"指南 . 对于#5,请记住POST不一定要使用
Content-Type: application/x-www-form-urlencoded
. 这可以很容易地成为JSON或CSV有效载荷 .每当看起来你需要一个新动词时,请考虑将该动词转换为名词 . 例如,将“激活”变为“激活”,将“验证”变为“验证” .
但是,根据你所写的内容,我会说你的应用程序有更大的问题 .
每当提出一个名为“参数”的资源时,它就会出现应该在每个项目团队成员心中发出危险信号 . '参数'可以逐字地应用于任何资源;它不够具体 .
“参数”究竟代表什么?可能有许多不同的东西,每个东西都应该有一个独立的资源专用于它 .
另一种解决方法 - 当你与最终用户(那些可能对编程知之甚少的人)讨论你的应用程序时,他们自己反复使用的单词是什么?
这些是您应该设计应用程序的词语 .
如果您尚未与潜在用户进行此转换 - 请立即停止所有操作,并且在您执行此操作之前不要编写另一行代码!只有这样,您的团队才能了解需要构建的内容 .
我对财务软件一无所知,但如果我不得不猜测,我会说一些资源可能会出现在“报告”,“付款”,“转账”和“货币”等名称上 .
软件设计过程的这一部分有很多好书 . 我可以推荐的两个是Domain Driven Design和Analysis Patterns .
您的网址设计与您的应用程序是否为REST是无关的 . 因此,短语“RESTful URLS”是无意义的 .
我认为你应该更多地阅读REST实际上是什么 . REST将URL视为不透明,因此不知道它们中的内容,无论是动词还是名词或其他什么 . 您可能仍希望设计URL,但这是关于UI而不是REST .
也就是说,让我们回答你的问题:最后两个案例不是RESTful,并且不适合任何类型的宁静方案 . 这些就是你可能称之为RPC的东西 . 如果您对REST非常认真,那么您必须重新思考应用程序的工作原理 . 要么是这样,要么放弃REST,只需将您的应用作为RPC应用程序 .
可能不是 .
这里的想法是你必须将所有东西视为一种资源,所以一旦一组参数有一个你可以引用它的URL,你只需添加
得到[parametersurl] / validationresults
发表[paramatersurl]
body:{command:“activate”}
但同样,激活的东西是RPC,而不是REST .
激活和验证要求是您尝试更改资源状态的情况 . 将订单“完成”或其他一些请求“提交”也没有什么不同 . 有许多方法可以对这些类型的状态更改进行建模,但我发现通常可以使用的方法是为同一个状态的资源创建集合资源,然后在集合之间移动资源以影响状态 .
例如创建一些资源,如,
如果要激活一组参数,请将该集添加到ActiveParameters集合中 . 您可以将参数集作为实体主体传递,也可以将URL作为查询参数传递,如下所示:
使用/ ValidatedParameters可以完成同样的事情 . 如果参数无效,则服务器可以向请求返回“错误请求”,以将参数添加到已验证参数的集合中 .
我会建议以下Meta资源和方法 .
使参数有效和/或验证它们:
检查参数是否有效且有效:
在REST环境中,每个URL都是唯一的资源 . 你有什么资源?金融计算器确实没有任何明显的资源 . 您需要深入了解您所调用的参数并提取资源 . 例如,贷款的摊还日历可能是资源 . 日历的URL可能包括start_date,term(以月或年为单位),期间(当利息复合时),利率和初始原则 . 有了所有这些 Value ,您就拥有了特定的付款日历:
现在,我不知道你在计算什么,但你的参数列表的概念听起来不是RESTful . 正如其他人所说,上面的要求听起来更像是XMLRPC . 如果您正在尝试REST,则需要使用名词 . 计算不是名词,它们是对名词起作用的动词 . 你需要转过来把名词从你的计算中拉出来 .
Edit: 确实,URI会阻止
GET
请求保持幂等 .但是,对于验证,使用HTTP状态代码来通知请求的有效性(创建新的或修改现有的'参数')将适合Restful模型 .
如果提交的数据无效且必须在重新提交之前更改请求(HTTP/1.1 Status Codes),则使用
400 Bad Request
状态代码进行报告 .这依赖于在提交时验证,而不是像在用例中那样推迟验证 . 其他答案对该场景有合适的解决方案 .