17

我已经在我的 WebAPI 项目中非常轻松地实现了 CRUD 功能。我现在正在尝试实现对象的存档(不是完全删除) - 如果只有ARCHIVEHTTP 方法。

我看到两个选项:

1)isArchived作为每个可归档实体的属性,即使归档与请求无关,它也必须包含在 PUT 和 POST 请求中。归档一个实体将是一个调用PUT /api/object/idisArchived 设置为 true 的问题。电线上看起来很笨重,但很安静。

2)有一个PUT /api/object/id/archive不需要正文的RPC-ish url。似乎是最有效率的,但并不安宁。

“通过 api 调用归档我的东西”空间中的每个人都在做什么?

4

4 回答 4

11

这是一个很好的问题,但我怀疑它最终可能会被标记为固执己见,因为我没有看到正确的答案……正如 OP 所说。

如果这对您的系统有意义,我建议将存档视为单独的对象存储(或者甚至是不同的对象类型)。对象设计不应依赖于数据库如何持久化您的数据。

因此,这是我现在能想到的最 RESTful设计(假设归档和更新始终是独立的操作——它们应该是):

典型(每个人都知道):

GET     /api/object     get all current objects
POST    /api/object     new current object
PUT     /api/object/id  update current object
DELETE  /api/object/id  delete current object
GET     /api/object/id  get current object

诡异之处:

POST    /api/object/id/archive  move object to archive (makes some REST sense)
POST    /api/object/id          move object from archive (muddy)

档案:

GET     /api/object/archive     get all archive objects
PUT     /api/object/id/archive  update archive object (if possible)
DELETE  /api/object/id/archive  delete archive object (tempting for unarchive)
GET     /api/object/id/archive  get archive object

或者,也许是存档 URL 的这些 mod 之一:

GET     /api/object/archive/id  get archive object
GET     /api/objectarchive/id   get archive object

但......

对于将对象移入和移出存档,上述内容感觉非常混乱(不是非常自我记录)。它还导致一些 REST API 设计痛苦,其中更新/删除/获取存档对象可能不需要特定于存档的功能。因此,我最终确定了这一点:

GET     /api/object                     get all objects
GET     /api/object?archived=false      get all current objects
GET     /api/object?archived=true       get all archive objects

POST    /api/object         new current object, returns all current objects*
PUT     /api/object/id      update object (current or archived; cannot change archive state)
DELETE  /api/object/id      delete object (current or archived), returns objects of same archive state as deleted*
GET     /api/object/id      get object    (current or archived)*

PUT /api/object/id/archive body:{archived:true}     move object to archive, returns all current objects*
PUT /api/object/id/archive body:{archived:false}    move object from archive, returns all archive objects*

* Return could be expanded/overridden with a query string if design calls for it.

诚然,这与我之前将存档视为单独的对象存储的说法大相径庭。然而,这种思考过程最终导致了这种设计妥协。在大多数方面,这对我来说感觉很好。

我个人不同意将查询字符串用于……呃……查询。所以,我没有。数据更改的有效负载——无论多么小——都应该进入正文(即当它不适合 REST 动词和 URL 时)。

于 2019-07-12T01:37:02.787 回答
5

如果您总是存档特定资源并且从不删除它,我会重新使用 DELETE 来实际存档。如果您真的需要区分删除和存档,我会这样做

GET /foo/33

200 OK
<foo id="33">blah</foo>


POST /archive
<foo id="33">blah</foo>

201 Created
Location: http://example.org/archive/foo/33

要不就

POST /archive?target=http://example.org/foo/33

201 Created
Location: http://example.org/archive/foo/33
于 2013-04-25T11:30:54.620 回答
1

我会使用这种/api/object/id?archive=true方法。

但是,至于你应该使用 PUT 还是 POST 取决于。如果您使用 PUT,则对同一 URL 的任何后续调用都不会更改有关资源的任何内容。如果您使用 POST,则实施者期望对该 URL 的任何后续调用确实会更改状态。(不要问我怎么做,我假设你会在这个上使用 PUT 动词。)

这是因为 PUT 操作应该是幂等的。请参阅此处的第 9.1.2 节:http: //www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

于 2013-04-24T21:07:32.653 回答
0

我可能会使用/api/object/id带有查询参数的端点,所以它看起来像/api/object/id?isArchived=true. 您仍然可以使用您正在使用的任何 HTTP 动词。

于 2013-04-24T20:58:28.063 回答