How to move a REST resource?

后端 未结 3 2080
无人共我
无人共我 2021-02-05 23:42

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

Initial state

  • /buckets/1 = foo
  • /buckets/2 = HT
相关标签:
3条回答
  • 2021-02-06 00:22
    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

    0 讨论(0)
  • 2021-02-06 00:30
    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).

    0 讨论(0)
  • 2021-02-06 00:40

    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.

    0 讨论(0)
提交回复
热议问题