REST API设计 - 按ID加载创建资源

时间:2015-05-08 09:16:38

标签: rest restful-url api-design

我的REST服务需要支持加载/重新加载资源的能力,而不是直接创建它。

到目前为止的

API:

GET /books
GET /books/12345
DELETE /books/12345

一本书看起来像:

{"id": 12345, "title": "three little bears", "author": ...}

是否

尚不清楚
Request:  PUT /books/12345
Response: HTTP 204 No Content

Request:  POST /books
Payload:  {"id": 12345}
Response: HTTP 201 Created, Location: /books/12345

是更好的方法来加载" /"重新加载"这本书。

详细信息:"加载" /"重新加载"将咨询数据库以通过id检索书籍,并将结果放在持久缓存中。缓存是GET请求的参考。书的属性可以在数据库中改变,这意味着"加载" /"重新加载"不是幂等的。只有管​​理员才能使用加载/重新加载和删除操作。

相信正确的方法是POST,因为PUT应该是幂等的。但是,一个POST看起来很奇怪,因为针对id = 12345的/ book的多个POST只会导致创建一个资源(虽然多次重新创建)

我已经考虑了下面的其他选项,但它们似乎更加恶劣:

* POST /books/12345/load
* POST /books/load, with payload {"id": 12345}
* POST /load/book, with payload {"id": 12345}

思想?

为了使问题更加复杂,我还想提供异步加载/重新加载操作,但我不想创建用户可以跟踪的操作/作业资源,我只是想要一个火-and-忘记。

示例:对于Book 12345,异步加载/重新加载到缓存中。我只需要服务来响应HTTP 202 Accepted,这已经足够了。无需询问加载/重新加载的进度。

TL; DR:我正在建立一个REST服务来提供书籍缓存。加载/重新加载和删除操作只能由管理员执行,而GET对所有人开放。加载/重新加载操作应该从数据库加载/重新加载记录。

2 个答案:

答案 0 :(得分:0)

If I get you correct, you have a

  • origin
  • database
  • clients

If a client global some_queue = None @app.route('/restart') def restart(): try: some_queue.put("something") return "Quit" def start_flaskapp(queue): some_queue = queue app.run(your_parameters) s a q = Queue() p = Process(target=start_flaskapp, args=[q,]) p.start() while True: #wathing queue, sleep if there is no call, otherwise break if q.empty(): time.sleep(1) else: break p.terminate() #terminate flaskapp and then restart the app on subprocess args = [sys.executable] + [sys.argv[0]] subprocess.call(args) , he fetches the resource from the database. The database doesn't know if this GET is altered in the meantime, it serves an outdated version? Therefore you want the client to book or book the resource to force the database to fetch the entry again from the origin?

Think about this:

The origin caches its content, the database caches its content and the client caches too.

If a user would hit F5 the client would reload the resource, right? Is this a good behaviour? no. Would it be better for the client to check wether the resource is outdated or not and only fetch if neccessary? yes. This could be achieved by sending a POST asking the server for the date of the last modification, if the clients retrieval-date is older he needs to fetch again, otherwise he can serve from cache.

Same would apply for the databse/origin-constellation. The database needs to validate its content is still the latest for the request and serve it or fetch it from the origin, update the caches and serve the new entry.

So the client would still PUT the resoure, what would be accurate if he doesn't want to alter the resource in any way.

答案 1 :(得分:0)

我认为你不应该在资源路径中使用动作名称(类似/books/12345/reload,...),因为它不是真正的RESTful。也就是说,我同意你的方法POST是正确的使用方法。

IMO,您应该使用方法POST作为资源路径/books/12345。它将对应于操作加载/重新加载并且可以是异步的,即返回此资源的状态代码202è. If you already have a method POST`,您应该考虑使用此博客文章中描述的策略:https://templth.wordpress.com/2015/03/20/handling-multiple-actions-for-a-post-method/。< / p>

希望它可以帮到你, 蒂埃里