【问题标题】:Am I designing this WCF RESTful interface correctly?我是否正确设计了这个 WCF RESTful 接口?
【发布时间】:2011-11-16 13:45:14
【问题描述】:

我正在使用 WcF 身份验证服务创建 WCF Web 服务,我需要的第一组功能是管理客户端的收件箱。客户端将由身份验证决定。

这是我对 API 的 RESTful 设计的尝试:


https://api.mydomain.com/v1/inbox/messages (GET)

在收件箱中返回一个应用了可选搜索过滤器的结果页

  • 计数 - 每页的记录数
  • 页面 - 要开始的页面
  • 排序 - (可选)要排序的字段
  • 搜索 - (可选)要搜索的文本

https://api.mydomain.com/v1/inbox/mark (POST)

将一条或多条消息标记为已读或未读

  • 操作 - MarkRead 或 MarkUnread
  • MessageIDs - 要标记的消息 ID 列表

https://api.mydomain.com/v1/inbox/archive (POST)

归档一条或多条消息

  • MessageIDs - 要归档的消息 ID 列表

我这样做对吗?如果不是,那么设计这个界面的更好方法是什么?

【问题讨论】:

  • 听起来像已读和未读可能是您第二个 URL 的一部分? https://api.mydomain.com/v1/inbox/mark/readhttps://api.mydomain.com/v1/inbox/mark/unread
  • 它们应该是两个独立的函数还是一个带参数的函数(这在 RESTful API 中更为规范)?
  • 如果你按照我的建议去做,那将是两个端点,对吧?就像在两个 URL 中一样。但是系统可以用同样的方法处理它们。
  • 好的,谢谢...最好有两个端点(每个动作一个端点)?如果他们更改数据,他们应该是 POST 吗?其余的都正确吗?
  • 如果他们更改数据,他们应该是 POST 或 PUT。这是一个比较何时使用stackoverflow.com/questions/630453/put-vs-post-in-restjcalcote.wordpress.com/2008/10/16/…的链接

标签: wcf api rest restful-authentication


【解决方案1】:

Martin Fowler 拥有 Richardson 成熟度模型的 good summary 以及创建 RESTful 服务所需的条件。 Jan 引用了 Roy Fielding 的一篇帖子,但除了超媒体(和HATEOAS)之外,还有一些步骤需要注意。

参考Richardson model,我认为您的 API 需要进行一些更改才能达到“3 级”(duh duh duhhhh)。 /v1/inbox/messages 集合看起来不错,并且仅支持 GET 表明它是用户的只读资源。然而,POSTing 动作和 ID 到 /v1/inbox/mark/v1/inbox/archive 只是通过 HTTP 隧道 RPC 样式的服务 - article 中的“级别 0”。

我建议将类似以下内容作为幼稚的非超媒体(即“2 级”)API:

  • 要检索所有邮件(在所有文件夹中)的摘要信息列表:

    GET /v1/messages HTTP/1.1
    Host: api.mydomain.com
    

    回复:

    content-type: text/xml
    
    <?xml version="1.0"?>
    <messages>
      <message subject="Subject" unread="true" id="1234" folder="inbox" />
      <message subject="Hello, world" unread="false" id="24" folder="inbox" />
      ...
    </messages>
    
  • 要检索完整的消息:

    GET /v1/messages/1234 HTTP/1.1
    Host: api.mydomain.com
    

    回复:

    content-type: text/xml
    
    <?xml version="1.0"?>
    <message subject="Subject" unread="true" id="1234" folder="inbox">
      Hi, this is the message.
    </message>
    
  • 编辑消息(例如,将其标记为已读并将其移动到存档文件夹):

    POST /v1/inbox/messages/1234 HTTP/1.1
    Host: api.mydomain.com
    content-type: text/xml
    
    <?xml version="1.0"?>
    <message id="1234" unread="false" folder="archive" />
    

    注意:这里我故意使用POST 而不是PUT 来表示部分更新。

其他需要注意的事项有:

  • 超媒体响应和媒体类型。坦率地说,其他人更好地解释了这一点(例如REST In Practice 书,或同一作者的InfoQ Coffee Cup example),但简而言之,您的回复应该向客户表明从他们最近的请求的回复中可能会采取哪些其他行动,并允许他们仅从单个 URI 发现整个 API。例如,上面有文件夹集合的含义。如果GET /v1/messages/1234 返回:

    <message subject="Subject" unread="true" id="1234" folder="inbox" >
      Message text here.
    
      <link rel="folder" href="http://api.mydomain.com/v1/folders/inbox" />
    </message>
    

    然后客户端将有一个具体的 URI 示例来尝试 OPTIONS,并很好地了解可能存在的内容。

  • 响应代码和内容:200 OK 很明显。如果用户无权查看特定消息,则回复 403 Forbidden,如果消息 ID 不存在,则回复 404 Not Found。每次返回错误时,向客户说明如何更正他们的请求(如果可能的话)。

【讨论】:

    【解决方案2】:

    Roy 的 POST 在遇到此类问题时很有帮助:http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

    因此:专注于定义媒体类型,而不是将您的客户端耦合到预定义的 URI 集。顺便说一句,它们无需注册即可使用。

    也许还可以看到http://www.nordsc.com/ext/classification_of_http_based_apis.html#http-type-one

    【讨论】:

      【解决方案3】:

      关于已读/未读部分 我不认为你需要一个职位。我认为你需要 put 方法 https://api.mydomain.com/v1/inbox/messageId/Read https://api.mydomain.com/v1/inbox/messageId/Unread

      创建新记录时需要发布并且您想要更新

      对于存档部分,我同意。只需记住返回归档过程的结果即可。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-08
        • 2015-12-13
        • 2012-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多