How to move a REST resource?

2020-05-27 04:51发布

I'm trying to move a resource from /buckets/1 to /buckets/2 such that:

Initial state

  • /buckets/1 = foo
  • /buckets/2 = HTTP 404

Final state

  • /buckets/1 = HTTP 301 to /buckets/2
  • /buckets/2 = foo

What's a RESTful way of asking the server to move a resource in this manner?

标签: rest
3条回答
孤傲高冷的网名
2楼-- · 2020-05-27 05:18

Answering my own question:

  • For the sake of this discussion let's assume that we are storing "balls" in buckets
  • The first thing to notice is that a ball's life-cycle is not determined by its containing bucket (moving a ball from one bucket to another does not delete the old ball). As such we should promote balls to a top-level resource: /balls
  • REST seems to work best in terms of symbolic links as opposed to inline values, so instead of GET /buckets/1 returning the value of the ball in the bucket let's have it return the URI of the ball instead.

We can then move balls as follows:

(examine original state)
GET /buckets/1: "balls = {'/balls/1'}"
GET /buckets/2: "balls = {}"
GET /balls/1: "bucket = /buckets/1"

(move ball into bucket #2)
PUT /balls/1: "bucket = /buckets/2"

(examine new state)
GET /buckets/1: "balls = {}"
GET /buckets/2: "balls = {'/balls/1'}"
GET /balls/1: "bucket = /buckets/2"

End-result: the ball's identity remains consistent as it moves across buckets and (most importantly) this operation is atomic.

查看更多
淡お忘
3楼-- · 2020-05-27 05:32
  1. Create original resource:

    PUT /bucket/1

  2. Call server procedure that responsible for moving resources:

    POST /bucket/1/move-to/2

  3. Original resource path now should return Moved status code:

    GET /bucket/1 HTTP 301

  4. Resource now should be available on new path:

    GET /bucket/2 HTTP 200

查看更多
该账号已被封号
4楼-- · 2020-05-27 05:34
  1. GET /buckets/1
  2. DELETE /buckets/1
  3. PUT /buckets/2 {data returned by #1}

That doesn't make the server 301, though. The alternative would be to use the WebDAV MOVE method, i.e. by creating your own @MOVE annotation using the @HttpMethod annotation:

import ...;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("MOVE")
public @interface MOVE {}

but doing so breaks REST's architectural principle of using HTTP as a uniform interface (RESTful Java).

查看更多
登录 后发表回答