Как переместить ресурс REST?

Я пытаюсь переместить ресурс от /buckets/1 до /buckets/2 таким образом, чтобы:

Начальное состояние

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

Конечное состояние

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

Что такое RESTful способ заставить сервер перемещать ресурс таким образом?

Ответ 1

Отвечая на мой собственный вопрос:

  • Для этого обсуждения предположим, что мы храним "шарики" в ведрах
  • Первое, что нужно заметить, это то, что жизненный цикл шара не определяется его содержащим ведром (перемещение шара из одного ведра в другое не удаляет старый шар). Таким образом, мы должны продвигать шары на ресурс верхнего уровня: /balls
  • REST, по-видимому, лучше всего работает с символическими ссылками, а не с встроенными значениями, поэтому вместо GET /buckets/1, возвращающего значение шара в ведро, пусть он возвращает URI шара.

Затем мы можем перемещать шары следующим образом:

(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"

Конечный результат: идентичность шара остается неизменной, поскольку она перемещается по ведрам и (что наиболее важно) эта операция является атомарной.

Ответ 2

  • GET /buckets/1
  • DELETE /buckets/1
  • PUT /buckets/2 {data returned by #1}

Это не делает сервер 301. Альтернативой было бы использовать метод WebDAV MOVE, т.е. Создав собственную аннотацию @MOVE, используя аннотацию @HttpMethod:

import ...;

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

но это нарушает архитектурный принцип REST использования HTTP в качестве единого интерфейса (RESTful Java).

Ответ 3

  • PUT/buckets/1

  • POST/move-bucket? from = 1 & to = 2

  • GET/buckets/1 HTTP 301

  • GET/buckets/2 HTTP 200