首页 文章

如何创建没有动词的REST URL?

提问于
浏览
275

我正在努力确定如何设计restful URL . 我完全是为了使用带名词的URL而不是动词的安静方法不明白如何做到这一点 .

我们正在创建一个实施金融计算器的服务 . 计算器采用一系列参数,我们将通过CSV文件上传 . 用例包括:

  • 上传新参数

  • 获取最新参数

  • 获取给定营业日期的参数

  • 激活一组参数

  • 验证一组参数

我收集的其余方法是拥有以下类型的URL:

/parameters
/parameters/12-23-2009

您可以通过以下方式实现前三个用例:

  • POST,在post请求中包含参数文件

  • 第一个网址的GET

  • 获取第二个URL

但是,如果没有动词,你如何做第4和第5个用例?你不需要像以下网址:

/parameters/ID/activate
/parameters/ID/validate

??

8 回答

  • 70

    也许是这样的:

    PUT /parameters/activation HTTP/1.1
    Content-Type: application/json; encoding=UTF-8
    Content-Length: 18
    
    { "active": true }
    
  • 1

    良好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 当某人对明显虚假的数据进行操作时;对于您的应用程序,这可能是一个验证错误;通常为未捕获的例外保留500

    • 401 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 teapot

    • Do 尽可能使用缓存标头
      当您可以轻松地将资源减少为哈希值时,

    • ETag 标头很好

    • Last-Modified 应该向您表明,保持资源更新时间的时间戳是一个好主意

    • Cache-ControlExpires 应该给出明智的 Value

    • Do 您可以在请求中尊重缓存标头的所有内容( If-None-ModifiedIf-Modified-Since

    • Do 在有意义时使用重定向,但这对于Web服务来说应该是罕见的

    关于您的具体问题,POST应该用于#4和#5 . 这些操作属于上述"RPC-like"指南 . 对于#5,请记住POST不一定要使用 Content-Type: application/x-www-form-urlencoded . 这可以很容易地成为JSON或CSV有效载荷 .

  • 0

    每当看起来你需要一个新动词时,请考虑将该动词转换为名词 . 例如,将“激活”变为“激活”,将“验证”变为“验证” .

    但是,根据你所写的内容,我会说你的应用程序有更大的问题 .

    每当提出一个名为“参数”的资源时,它就会出现应该在每个项目团队成员心中发出危险信号 . '参数'可以逐字地应用于任何资源;它不够具体 .

    “参数”究竟代表什么?可能有许多不同的东西,每个东西都应该有一个独立的资源专用于它 .

    另一种解决方法 - 当你与最终用户(那些可能对编程知之甚少的人)讨论你的应用程序时,他们自己反复使用的单词是什么?

    这些是您应该设计应用程序的词语 .

    如果您尚未与潜在用户进行此转换 - 请立即停止所有操作,并且在您执行此操作之前不要编写另一行代码!只有这样,您的团队才能了解需要构建的内容 .

    我对财务软件一无所知,但如果我不得不猜测,我会说一些资源可能会出现在“报告”,“付款”,“转账”和“货币”等名称上 .

    软件设计过程的这一部分有很多好书 . 我可以推荐的两个是Domain Driven DesignAnalysis Patterns .

  • 0

    您的网址设计与您的应用程序是否为REST是无关的 . 因此,短语“RESTful URLS”是无意义的 .

    我认为你应该更多地阅读REST实际上是什么 . REST将URL视为不透明,因此不知道它们中的内容,无论是动词还是名词或其他什么 . 您可能仍希望设计URL,但这是关于UI而不是REST .

    也就是说,让我们回答你的问题:最后两个案例不是RESTful,并且不适合任何类型的宁静方案 . 这些就是你可能称之为RPC的东西 . 如果您对REST非常认真,那么您必须重新思考应用程序的工作原理 . 要么是这样,要么放弃REST,只需将您的应用作为RPC应用程序 .

    可能不是 .

    这里的想法是你必须将所有东西视为一种资源,所以一旦一组参数有一个你可以引用它的URL,你只需添加

    得到[parametersurl] / validationresults

    发表[paramatersurl]

    body:{command:“activate”}

    但同样,激活的东西是RPC,而不是REST .

  • 11

    激活和验证要求是您尝试更改资源状态的情况 . 将订单“完成”或其他一些请求“提交”也没有什么不同 . 有许多方法可以对这些类型的状态更改进行建模,但我发现通常可以使用的方法是为同一个状态的资源创建集合资源,然后在集合之间移动资源以影响状态 .

    例如创建一些资源,如,

    /ActiveParameters
    /ValidatedParameters
    

    如果要激活一组参数,请将该集添加到ActiveParameters集合中 . 您可以将参数集作为实体主体传递,也可以将URL作为查询参数传递,如下所示:

    POST /ActiveParameters?parameter=/Parameters/{Id}
    

    使用/ ValidatedParameters可以完成同样的事情 . 如果参数无效,则服务器可以向请求返回“错误请求”,以将参数添加到已验证参数的集合中 .

  • 17

    我会建议以下Meta资源和方法 .

    使参数有效和/或验证它们:

    > 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': '...'}
    < }
    <
    
  • 6

    在REST环境中,每个URL都是唯一的资源 . 你有什么资源?金融计算器确实没有任何明显的资源 . 您需要深入了解您所调用的参数并提取资源 . 例如,贷款的摊还日历可能是资源 . 日历的URL可能包括start_date,term(以月或年为单位),期间(当利息复合时),利率和初始原则 . 有了所有这些 Value ,您就拥有了特定的付款日历:

    http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000
    

    现在,我不知道你在计算什么,但你的参数列表的概念听起来不是RESTful . 正如其他人所说,上面的要求听起来更像是XMLRPC . 如果您正在尝试REST,则需要使用名词 . 计算不是名词,它们是对名词起作用的动词 . 你需要转过来把名词从你的计算中拉出来 .

  • 980

    Edit: 确实,URI会阻止 GET 请求保持幂等 .


    但是,对于验证,使用HTTP状态代码来通知请求的有效性(创建新的或修改现有的'参数')将适合Restful模型 .

    如果提交的数据无效且必须在重新提交之前更改请求(HTTP/1.1 Status Codes),则使用 400 Bad Request 状态代码进行报告 .

    这依赖于在提交时验证,而不是像在用例中那样推迟验证 . 其他答案对该场景有合适的解决方案 .

相关问题