REST Web Services API 设计

15

我只是想获得有关如何规划我的API的反馈。下面是虚拟方法。这是结构:

GET http://api.domain.com/1/users/ <-- returns a list of users
POST http://api.domain.com/1/users/add.xml <-- adds user
POST http://api.domain.com/1/users/update.xml <-- updates user
DELETE (or POST?) http://api.domain.com/1/users/delete.xml <-- deletes user

问题:

  1. 只使用GET和POST方法是否可行?
  2. 如果我计划依赖文件名来指示要执行的操作(例如将add.xml用于添加),这是一个好主意吗?还是像这样做更好:POST http://api.domain.com/1/users/add/data.xml
  3. 保持这些资源版本化的好方法是什么?在我的示例中,我使用在域名后面加上/1/来表示版本1。其他选择包括:http://api1.domain.com... 或 http://api-1.domain.com... 或 http://apiv1.domain.com... 或 http://api-v1.domain.com... 或 http://api.domain.com/v1/... 或
  4. 最佳身份验证方式是什么?

REST API架构 - 最佳实践 - Techie
5个回答

39
在深入了解REST之前,这里有一些术语你需要掌握:
资源 - 你想要在API中提供的东西/数据(在本例中是“用户”)
URI - 资源的唯一标识符。不应该包含任何关于正在执行的方法的信息(例如不应该包含“添加”或“删除”)。但是,URI的结构并不会使你的应用程序更加RESTful——这是一个常见的误解。
统一接口 - 你可以对资源执行的固定集合操作,在大多数情况下,这是HTTP。每个HTTP方法的目的都有明确的定义。
你现在的URI最不符合RESTful的地方就是它们直接包含有关正在执行的操作的信息。URI只是ID,仅此而已!
让我们以一个真实的例子来说明。我的名字是Nathan。“Nathan”可以被认为是我的ID(或者按照RESTful术语,URI——为了本例子的目的,假设我是唯一的“Nathan”)。无论你想如何与我交互,我的名字/ID都不会改变,例如当你想要和我打招呼时,我的名字不会变成“NathanSayHello”。
对于REST来说也是一样的。当您想要更新用户时,由http://api.domain.com/users/1标识的用户不会更改为http://api.domain.com/users/1/update.xml。您使用的方法(例如PUT)已经暗示了您想要更新该用户的事实。
这是我对您的URI的建议。
# Retrieve info about a user 
GET http://api.domain.com/user/<id>

# Retrieve set all users
GET http://api.domain.com/users

# Update the user IDed by api.domain.com/user/<id>
PUT http://api.domain.com/user/<id>

# Create a new user.  The details (even <id>) are based as the body of the request
POST http://api.domain.com/users

# Delete the user ID'd by api.domain.com/user/<id>
DELETE http://api.domain.com/user/<id>

关于您的问题:

  1. 在适当的情况下使用PUT和DELETE,并避免过度使用POST来处理这些功能,因为它违反了HTTP对POST的定义。 HTTP是您的统一接口。 它是与API用户交互方式的合同。 如果您破坏HTTP,则会破坏此合同。

  2. 完全删除"add"。 使用HTTP的Content-Type标头指定发布的数据的MIME类型。

  3. 您是指API的版本还是资源的版本? ETag和其他响应标头可用于资源版本控制。

  4. 这里有很多选项。基本的HTTP身份验证(易于但不安全),摘要验证,像AWS一样的自定义验证。OAuth也是可能的。如果安全性非常重要,我使用客户端SSL证书。


3
回复加1,但PUT/DELETE需要具有幂等性,而不是POST。POST可以随心所欲地使用。 "幂等"只是指如果操作重复两次,则会产生相同的结果-用数学术语来说,这是 f(f(x)) = f(x)。在我们的例子中,如果将两个相同的PUT应用于同一资源,则结果必须与仅执行1个相同。另一方面,POST取决于开发人员给定的语义,可能会产生不同的结果(例如,连续两次POST可能会发送2封电子邮件)。 - Nas Banov
你是完全正确的。应该写成“普遍缺乏幂等性”,因为往往会创建资源(或者在你的例子中,创建一个发送电子邮件的作业),这绝对不是幂等的。我会相应地调整帖子。 - nategood

7

1)在您的设计中可能不是这样。POST不是幂等的!因此,您不应将其用于更新或删除,而应改用来自Rest的PUT和DELETE。

2)更好的选择是在WS调用中使用头部Content-Type,例如:application/xml

3)同样,在头部Content-Type中,您可以使用它:application-v1.0/xml

4)不确定是否最好,但可能最简单的方法是在RFC 2617中使用HTTP内置的身份验证机制。例如:AWS Authentication


你对(1)的论述不充分。POST 不是“非幂等”的,而是“不一定是幂等的”。由于它定义了服务器端的语义,他的 POST 可能是幂等的,这符合 HTTP 和整个世界的要求。 - Nas Banov
@NasBanov 从w3.org的Http方法文档http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html中查看第9.1.2节幂等方法。Post从未被列为可能的幂等方法。 - Diego Dias
@DiegoDias,9.1.2讨论了GET/HEAD/PUT/DELETE,对POST没有任何影响。如果我说Joe和Moe很诚实,这并不意味着Billy是个骗子。[9.5]“POST方法执行的实际功能由服务器确定,通常取决于请求URI”-例如,如果我有一个(翻转)灯开关,它将不是幂等的。但如果它是一个“ON”按钮,那么它将是幂等的。 - Nas Banov
1
请参考第9.6节:“POST和PUT请求的根本区别体现在Request-URI的不同含义上。 在POST请求中,URI标识将处理所封装实体的资源。相反,在PUT请求中,URI标识了请求所附带实体。 "因此,如果您想使用PUT,您需要提前知道userID并执行PUT http://api.domain.com/1/user/123654。如果您期望添加用户并获得返回的ID,则应执行 POST http://api.domain.com/1/users - Nas Banov

0

我基于头部进行了身份验证。类似这样的:

X-Username:happy-hamster
X-Password:notmyactualpassword

如果您关心安全性 - 请通过SSL进行。 当然,还有其他实现方式。例如,亚马逊的S3: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html 如果您没有能力进行PUT和DELETE请求,将它们隧道化通过POST是一个好的做法。在这种情况下,操作在URL中指定。如果我没记错的话,RoR正是这样做的:
POST http://example.com/foos/2.xml/delete

或者

POST http://example.com/foos/3.xml/put

...

<foo>
    <bar>newbar</bar>       
</foo>

这有点离题,但是关于版本控制和 REST 的整体来说,你可能想看一下 CouchDB。这里有一本在线可用的好书


0
  1. 在REST中,HTTP“动词”用于表示操作类型:仅使用“GET”和“POST”无法表达所有CRUD操作。

  2. 不是的:资源的URL通常应该出现“文档标识符”的位置。

  3. “文档”的版本可以在创建/修改所述资源时通过HTTP响应头传输。服务器应该负责唯一标识资源-在客户端上尝试这样做将证明是一个艰巨的挑战,即保持一致性。

当然,关于这个主题有许多变化...


-1

使用post方法来创建和删除功能并不是一个良好的rest api设计策略。使用Put来创建,post来更新,delete来删除资源。 要了解更多关于设计rest apis的信息,请访问链接 - 设计rest apis的最佳实践


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接